Как использовать методы в классе ObjectContext, если я использую IObjectSet <T>для модульного теста? - PullRequest
1 голос
/ 10 ноября 2010

Я использую EF4 с POCO и пытаюсь сделать его тестируемым. Поэтому я создаю интерфейс IObjectContext следующим образом:

public interface IObjectContext
    {
        IObjectSet<Employee> Employees { get; }
        IObjectSet<Team> Teams { get; }
        void Commit();
    }

Затем я изменил тип свойств на IObjectSet в моем реальном классе ObjectContext следующим образом:

public partial class HRManagementEntities : ObjectContext, IUnitOfWork
    {
        // skip some codes here...........

        public IObjectSet<Employee> Employees
        {
            get { return _employees  ?? (_employees = CreateObjectSet<Employee>("Employees"));         
        }
        private IObjectSet<Employee> _employees;

        public IObjectSet<Team> Teams
        {
            get { return _teams  ?? (_teams = CreateObjectSet<Team>("Teams")); }
        }
        private IObjectSet<Team> _teams;

        public void Commit()
        {
            SaveChanges();
        }
}

В моем слое обслуживания используйте EF следующим образом:

public class Service
    {
         private IObjectContext ctx;

         public HRService(IObjectContext ctx)
         {
            this.ctx = ctx;
         }

         public List<Team> GetAllTeams()
         {
            return ctx.Teams.ToList();
         }
    }

Вот моя проблема: как вызывать методы в ObjectContext, например, ApplyCurrentValues ​​(), ExecuteStoreCommand () и т. Д ...?

Нужно ли реализовывать эти методы в IObjectContext для использования?

EDIT

Как совет RPM, я создал следующий метод расширения для метода ApplyCurrentValues ​​(), другие методы могут быть расширены таким же образом.

public static T UpdateModel<T>(this IObjectSet<T> iObjectSet, T currentEntity) where T : class
        {
            ObjectSet<T> objectSet = iObjectSet as ObjectSet<T>;
            if (objectSet == null || currentEntity == null)
            throw new ArgumentNullException();
            return objectSet.ApplyCurrentValues(currentEntity);
        }

1 Ответ

2 голосов
/ 10 ноября 2010

Вам нужно создать методы расширения для необходимых вам методов и привести IObjectSet к ObjectSet.

Например, если вам нужно сделать .Include (энергичная загрузка), используйте этот метод расширения:

public static IQueryable<TSource> Include<TSource>(this IQueryable<TSource> source, string path)
    {
        var objectQuery = source as ObjectQuery<TSource>;

        if (objectQuery != null)
        {
            objectQuery.Include(path);
        }

        return source;
    }

Вы могли бы , вероятно, сделать то же самое для IObjectContext, но не уверены, почему вы даже издеваетесь над этим. Вы не должны открывать OC за пределами хранилища, только хранилище должно знать о OC.

В вашем примере ваш сервис вызывает ctx.Teams для сущностей / репозитория.

IMO, ваша служба должна вызывать ctx.Find, который будет строго типизирован (с помощью обобщений) для контекста объекта Teams. (IRepository)

Обычной ловушкой является чрезмерное издевательство над вещами. Не надо издеваться над всем ради него, надрать функциональность, необходимую для юнит-тестирования.

Если вы хотите абстрагироваться от контекста объекта, используйте шаблон «Единица работы».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...