Во-первых, у ObjectResult нет общедоступного конструктора без параметров, поэтому сначала необходимо создать тестируемую оболочку для ObjectResult. Ответ @forsvarir (https://stackoverflow.com/users/592182/forsvarir) в этом посте заставил меня задуматься правильно в этих строках (EF6 - не может имитировать возвращаемое значение для ObjectResult‹T› для модульного теста):
using System.Data.Entity.Core.Objects;
namespace MyNamespace.Mocks
{
public class TestableEfObjectResult<T> : ObjectResult<T> { }
}
Конечно, DbContext нужно издеваться. Затем необходимо настроить ваш метод для возврата соответствующего имитированного перечислителя. Для удобства я создал метод, помогающий в создании фиктивных результатов EF, чтобы мой тестовый код не был загроможденным и избыточным. Это может жить в каком-то утилитарном классе, который у вас есть для ваших тестов, хотя я просто включил его здесь как частный метод. Ключевым моментом здесь является то, что результат фиктивного объекта должен возвращать перечислитель при вызове GetEnumerator:
namespace MyNamespace.Mocks
{
public class MockSomeDbEntities
{
public static Mock<SomeDbEntities> Default
{
get
{
var mockSomeDbEntities = new Mock<SomeDbEntities>();
mockSomeDbEntities
.Setup(e => e.SomeMethod(It.IsAny<int>()))
.Returns(MockEfResult(Enumerators.SomeCollection).Object);
return mockSomeDbEntities;
}
}
private static Mock<TestableEfObjectResult<T>> MockEfResult<T>(Func<IEnumerator<T>> enumerator) where T : class
{
var mock = new Mock<TestableEfObjectResult<T>>();
mock.Setup(m => m.GetEnumerator()).Returns(enumerator);
return mock;
}
}
}
Класс Enumerators, который я создал для передачи перечислителя всякий раз, когда функция вызывается на макете, просто выглядит следующим образом. В этом примере у меня есть поддельный счетчик, создающий 5 строк данных:
using System;
using System.Collections.Generic;
namespace MyNamespace.FakeData
{
public static class Enumerators
{
public static IEnumerator<Some_Result> SomeCollection()
{
yield return FakeSomeResult.Create(1);
yield return FakeSomeResult.Create(2);
yield return FakeSomeResult.Create(3);
yield return FakeSomeResult.Create(4);
yield return FakeSomeResult.Create(5);
}
}
}
И, как видите, это просто полагается на класс, который создает каждую фальшивую строку данных:
namespace MyNamespace.FakeData
{
public static class FakeSomeResult
{
public static Some_Result Create(int id)
{
return new Some_Result
{
Id = id,
};
}
}
}
Возможность имитировать на этом уровне действительно позволяет мне выполнять BDD и только имитировать или подделывать периферийные устройства, никогда не имитируя и не подделывая мой код, поэтому я получаю полное (r) тестовое покрытие.
Надеюсь, это поможет тем, кто, как и я, искал хороший и чистый способ издеваться над Entity Framework 6.
person
Jim Speaker
schedule
28.08.2015