2016-08-17 1 views
1

Меня попросили написать модульные тесты с использованием рамки Moq. Я довольно новичок в том, как писать тесты Moq в C#.реальная цель фрейма moq

Я иду через этот MSDN link

Вот что я делаю прямо сейчас, как мы используем инъекции зависимостей на хранилище

//Repository 
public interface IRepo 
{ 
    IQueryable<MyModel> GetById(long userId); 
} 

public class Repo : BaseManager, IRepo 
{ 
    public Repo(myDbContext context) 
    { 
     dbContext = context; //dbContext is from BaseManager class 
    } 
    public IQueryable<MyModel> GetById(long userId) 
    { 
     return dbContext.MyModel.Where(x => x.IsActive && x.UserId == userId); 
    } 
} 

//Test class 
public class Test 
{ 
    Mock<DbSet<MyModel>> mockSet; 
    Mock<myDbContext> mockContext; 
    Mock<IRepo> mockRepository; 

    [TestInitialize] 
    public void Setup() 
    { 
     var data = new List<MyModel>{ 
      //3 records 
     }.AsQueryable(); 

     var mockSet = new Mock<DbSet<MyModel>>(); 
     mockSet.As<IQueryable<MyModel>>().Setup(m => m.Provider).Returns(data.Provider); 
     mockSet.As<IQueryable<MyModel>>().Setup(m => m.Expression).Returns(data.Expression); 
     mockSet.As<IQueryable<MyModel>>().Setup(m => m.ElementType).Returns(data.ElementType); 
     mockSet.As<IQueryable<MyModel>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); 

     var mockContext = new Mock<myDbContext>(); 
     mockContext.Setup(c => c.MyModel).Returns(mockSet.Object); 

     mockRepository = new Mock<IRepo>(); 
     mockRepository.Setup(m => m.GetById(It.IsAny<long>())).Returns(data); //Here the GetById method is set to return all 3 records set in data object. 
    } 

    [TestMethod] 
    public void Test_Mock_For_Nothing() 
    { 
     var controller = new MyController(mockRepository.Object); 
     var result = controller.GetById(1); //this will call GetById method in the repository 

     Assert.AreEqual(result.Count(), 1);//This will fail as we will get count as 3 
    } 
} 

Таким образом, логика в хранилище никогда не выполняется, хотя Я издевался над контекстом и хранилищем. Поскольку метод GetById будет напрямую возвращать результат с 3 записями в соответствии с фиктивными данными.

Я ожидаю, что фиктивные данные будут отфильтрованы на основе логики в методе репозитория. Возможно ли это с помощью Moq?

Какова реальная цель использования инфраструктуры Moq, когда код репозитория не выполняется?

+0

Где вы указываете 'mockRepository'' mockContext' ?? –

+0

Почему вы издеваетесь над контекстом, когда вы уже издевались над хранилищем. Сама природа насмешек говорит, забыть все, кроме одного метода, который я использую: «Этот метод должен дать мне эти данные». В этих обстоятельствах нет необходимости беспокоиться об этом контексте. –

+0

@CallumLinington Мне нужны данные, которые будут проходить через репозиторий и возвращать действительный список элементов.Так что я тоже издеваюсь над контекстом –

ответ

3

Учитывая, что вы издевались над своим хранилищем, не видя логики контроллера, я не уверен, почему вам нужно будет издеваться над dbContext. Но эффективно с этим тестом вы проверяете логику контроллера, а не репозиторий, поскольку вы издеваетесь над репозиторием и что возвращается из GetById в репозитории.

Если вы хотите протестировать логику фильтра в репозитории, вам нужно будет высмеять dbContext (как вы это сделали), и в тесте создайте новый конкретный экземпляр репозитория и проверьте данные, которые возвращаются из вызова GetByID.

Итак, вы издеваетесь над dbContext.MyModel, возвращая три элемента и разрешаете функции Where where выполнять фильтрацию.

Существует много полезной информации о том, как использовать насмешливую фреймворк, но у каждого есть несколько разные мнения о том, что вы должны тестировать, и небольшой блок, который вы должны тестировать в одном модульном тесте, опыт и личные предпочтения являются ключом здесь ,

+0

Должен ли я удалять насмешку над хранилищем? Я имею в виду 'mockRepository.Setup' –

+0

Ну, это действительно так, чтобы иметь тест уровня контроллера и учитывая, что вы издевались над своим репозиторием, что ваш контроллер просто возвращается прямо из репозитория. Это может показаться бессмысленным, но если кто-то модифицирует логику контроллера в будущем и нарушит это, тогда вы знаете, что логика контроллера больше не просто возвращает данные из вашего репозитория. Я думаю, вам также нужен тест репозитория, и в этом тесте репозитория вы можете проверить свою логику фильтрации. Таким образом, в вашем контрольном тесте просто издеваются над репозиторием и в вашем тестовом репозитории просто издеваются над контекстом db – Corporalis

+0

Я получаю «Исключение из броска:« Castle.DynamicProxy.InvalidProxyConstructorArgumentsException »в Moq.dll, передавая издевательский контекст конкретному конструктору репо. Есть идеи ? –

0

с модульными тестами, которые вы пытаетесь проверить/упростить свою бизнес-логику. в ваших репозиториях не должно быть BL (Businesslogic). с вашей MOCK Framework вы отключите, думайте, что вы не хотите тестировать. -> Репозиторий = доступ к данным. С этим вы можете изменить свой способ получения своих данных (репозитория) без каких-либо изменений в своих бизнес-тестах/блоках:

PS: если вы хотите протестировать свои репозитории или даже больше, вы должны стремиться к интеграционным испытаниям или даже для тестов «от конца до конца».

1

С точки зрения вашего теста я бы сказал, что очень мало пользы от использования насмешливой структуры или даже с этим тестом. Мои мысли:

1) Если у вас есть хранилище написать интеграционный тест, как вы хотите, чтобы доказать, что вы возвращаете данные из базы данных/веб-службы и т.д.

2) Использование Moq или RhinoMocks в ситуациях, когда вы хочу протестировать некоторую бизнес-логику/поведение

+1

Я задаю ожидания перед запуском модульного теста (используя метод '.Returns'). Итак, я знаю, что тест пройдет. Какой смысл насмехаться над всем, когда я знаю, что это работает. –

+0

Ну, вы знаете, что это работает с использованием IQueryable, но это хорошо, но когда это связано с SQL, некоторые команды в LINQ будут недоступны. Поэтому всегда лучше иметь интеграционные тесты для стороны репозитория. –