Модульное тестирование EF - как извлечь код EF из BL?

я прочиталso much (десятки постов) об одном:

How to unit test business logic code that has Entity Framework code in it.

У меня есть сервис WCF с 3 слоями:

Service Layer Business Logic Layer Data Access Layer

Моя бизнес-логика используетDbContext для всех операций с базой данных. Все мои сущности теперь являются POCO (раньше это был ObjectContext, но я это изменил).

я прочиталLadislav Mrnka's ответВот а такжеВот  по причинам, почему мы должныnot издеватьсяDbContext.

Он сказал: "That is the reason why I believe that code dealing with context / Linq-to-entities should be covered with integration tests and work against the real database."

а также: "Sure, your approach works in some cases but unit testing strategy must work in all cases - to make it work you must move EF and IQueryable completely from your tested method."

Мой вопрос - как вы этого добиваетесь ???

public class TaskManager
{
    public void UpdateTaskStatus(
        Guid loggedInUserId,
        Guid clientId,
        Guid taskId,
        Guid chosenOptionId,
        Boolean isTaskCompleted,
        String notes,
        Byte[] rowVersion
    )
    {
        using (TransactionScope ts = new TransactionScope())
        {
            using (CloseDBEntities entities = new CloseDBEntities())
            {
                User currentUser = entities.Users.SingleOrDefault(us => us.Id == loggedInUserId);
                if (currentUser == null)
                    throw new Exception("Logged user does not exist in the system.");

                // Locate the task that is attached to this client
                ClientTaskStatus taskStatus = entities.ClientTaskStatuses.SingleOrDefault(p => p.TaskId == taskId && p.Visit.ClientId == clientId);
                if (taskStatus == null)
                    throw new Exception("Could not find this task for the client in the database.");

                if (taskStatus.Visit.CustomerRepId.HasValue == false)
                    throw new Exception("No customer rep is assigned to the client yet.");
                TaskOption option = entities.TaskOptions.SingleOrDefault(op => op.Id == optionId);
                if (option == null)
                    throw new Exception("The chosen option was not found in the database.");

                if (taskStatus.RowVersion != rowVersion)
                    throw new Exception("The task was updated by someone else. Please refresh the information and try again.");

                taskStatus.ChosenOptionId = optionId;
                taskStatus.IsCompleted = isTaskCompleted;
                taskStatus.Notes = notes;

                // Save changes to database
                entities.SaveChanges();
            }

            // Complete the transaction scope
            ts.Complete();
        }
    }
}

В прилагаемом коде есть демонстрация функции из моей бизнес-логики. Функция имеет несколько «поездок». в базу данных. Я не понимаю, как именно я могуstrip код EF из этой функции в отдельную сборку, так что я могуunit test эта функция (путем введения некоторых поддельных данных вместо данных EF), иintegrate test сборка, которая содержит «функции EF».

Может ли Ладислав или кто-то еще помочь?

[Edit]

Вот еще один пример кода из моей бизнес-логики. Я не понимаю, как я могу «переместить код EF и IQueryable». из моего проверенного метода:

public List<UserDto> GetUsersByFilters(
    String ssn, 
    List<Guid> orderIds, 
    List<MaritalStatusEnum> maritalStatuses, 
    String name, 
    int age
)
{
    using (MyProjEntities entities = new MyProjEntities())
    {
        IQueryable<User> users = entities.Users;

        // Filter By SSN (check if the user's ssn matches)
        if (String.IsNullOrEmusy(ssn) == false)
            users = users.Where(us => us.SSN == ssn);

        // Filter By Orders (check fi the user has all the orders in the list)
        if (orderIds != null)
            users = users.Where(us => UserContainsAllOrders(us, orderIds));

        // Filter By Marital Status (check if the user has a marital status that is in the filter list)
        if (maritalStatuses != null)
            users = users.Where(pt => maritalStatuses.Contains((MaritalStatusEnum)us.MaritalStatus));

        // Filter By Name (check if the user's name matches)
        if (String.IsNullOrEmusy(name) == false)
            users = users.Where(us => us.name == name);

        // Filter By Age (check if the user's age matches)
        if (age > 0)
            users = users.Where(us => us.Age == age);


        return users.ToList();
    }
}

private   Boolean   UserContainsAllOrders(User user, List<Guid> orderIds)
{
    return orderIds.All(orderId => user.Orders.Any(order => order.Id == orderId));
}

Ответы на вопрос(2)

Ваш ответ на вопрос