Testowanie jednostek EF - jak wyodrębnić kod EF z BL?

przeczytałemtak wiele (dziesiątki postów) o jednej rzeczy:

Jak połączyć testowy kod logiki biznesowej z kodem Entity Framework.

Mam usługę WCF z 3 warstwami:

Warstwa usługowaWarstwa logiki biznesowejWarstwa dostępu do danych

Moja logika biznesowa używaDbContext dla wszystkich operacji na bazie danych. Wszystkie moje elementy są teraz POCOs (kiedyś były ObjectContext, ale zmieniłem to).

przeczytałemLadislava Mrnki odpowiedźtutaj itutaj o powodach, dla których powinniśmynie udawać fałszywegoDbContext.

Powiedział:„To jest powód, dla którego uważam, że kod dotyczący kontekstu / Linq-to-entity powinien być objęty testami integracyjnymi i działać w oparciu o prawdziwą bazę danych”.

i:„Oczywiście, twoje podejście działa w niektórych przypadkach, ale strategia testowania jednostek musi działać we wszystkich przypadkach - aby to działało, musisz całkowicie przenieść EF i IQueryable z testowanej metody”.

Moje pytanie brzmi - jak to osiągnąć ???

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();
        }
    }
}

W dołączonym kodzie jest demonstracja funkcji z mojej logiki biznesowej. Funkcja ma kilka „podróży” do bazy danych. Nie rozumiem, jak mogę to zrobićrozebrać się kod EF z tej funkcji do osobnego zespołu, dzięki czemu jestem w stanietest jednostkowy ta funkcja (poprzez wstrzyknięcie fałszywych danych zamiast danych EF), orazzintegrować test zespół, który zawiera „funkcje EF”.

Czy Ladislav lub ktokolwiek inny może pomóc?

[Edytować]

Oto kolejny przykład kodu z mojej logiki biznesowej, nie rozumiem, jak mogę „przenieść kod EF i IQueryable” z mojej testowanej metody:

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));
}

questionAnswers(2)

yourAnswerToTheQuestion