Мокинг объекта с помощью Moq, использование Ninject при выполнении UnitTesting

У меня проблемы с использованием Moq в проекте UnitTesting с Ninject.

Сначала несколько строк о моем решении. Он содержит несколько проектов (BussinesLogic, DAL, Infrastructure ...). Моя цель - провести UnitTest по логике, которую я использую в проекте BussinessLogic. Решение в основном предназначено для службы Windows, но я добавил логику, чтобы ее можно было запускать автономно. Я использую Ninject и указываю погоду, я хочу использовать ProductionModule или TestingModule (служба Windows использует ProductionModule, консольное приложение использует TestingModule)

Я использую заводской шаблон, чтобы получить ядро ​​ninject, когда оно мне нужно внутри моего приложения.

Мой TestingModule наследуется от NinjectModule, где я переопределяю метод Load () и выполняю привязку. Например:

Bind<IStorageManager>().To<StubStorageManager>();

У меня есть StubStorageManager, но он пуст. Он содержит просто объявление методов из IStorageManager.

Я бы хотел (с точки зрения непрофессионала): создать unitTest, в котором я бы создал новое ядро, указав TestingModule в качестве параметра. Затем я хотел бы создать фиктивный объект (скажем, макет IStorageManager) storageManagerMock. Какой-то метод в IStorageManager возвращает объект messageObject, поэтому мне, вероятно, нужно было бы высмеять это тоже, потому что бизнес-логика что-то делает на основе этого messageObject. Поэтому я хотел бы каким-то образом установить свойства для этого объекта сообщения, а затем вызвать для него какой-нибудь метод businessLogic, чтобы я мог видеть, правильно ли работает логика.

Надеюсь, я не слишком усложнял это.

Пожалуйста, потерпите меня, я совершенно не знаком с издевательствами и инъекциями зависимостей, но готов учиться.


person Alex Dee    schedule 29.04.2011    source источник
comment
Возможный дубликат: stackoverflow.com/questions/1465849/using- ioc-for-unit-testing   -  person Mark Seemann    schedule 29.04.2011


Ответы (1)


Я сомневаюсь, что вы действительно хотите использовать Ninject в своих тестах. Весь смысл использования ninject в том, что вы можете все разъединить. Вы также хотите попытаться сохранить все изолированным от самого контейнера зависимостей, если это возможно. Передайте его, если необходимо, или передайте фабрики, которые создают требуемый объект и передают контейнер в фабрику.

Я подозреваю, что вы, вероятно, захотите сделать что-то вроде этого:

public void ATest(){
   //create a mock StorageManager
   var managerMock = new Mock<IStorageManager>();
   //create a mock MessageObject to be used by business logic
   var messageObjectMock = new Mock<MessageObject>();

   //have the storage manager return the mock message when required
   managerMock.Setup(x => x.GetMessageObject()).Returns(messageObjectMock.Object);
   //set up message expectations
   messageObjectMock.Setup(x => x.ThisValueExpected).Returns(10);
   messageObjectMock.Setup(x => x.ThisFunctionShouldBeCalled()).Verifiable("Function not called.");

   //thing to test
   BusinessLogicObject blo = new BusinessLogicObject(managerMock.Object);
   blo.DoTheThingImTesting();

   //make sure the business logic called the expected function, or do whatever check you need...
   messageObjectMock.Verify();
 }
person Russell Troywest    schedule 29.04.2011
comment
Это именно то, чем я хотел заниматься. Хорошо, так что использование контейнера DI в тесте - это плохо, я так понимаю? Почему это так? Я подумал, что, используя его, это может упростить мои тесты, поэтому мне не нужно писать: var p = new Program(new StubHealthMonitor(), storageManagerMock, new LogManager(), new StubConfigurationManager()); Я в основном думал, что позволю контейнеру DI позаботиться обо всех вещах, которые напрямую не связаны с этим тестом, но о том, что включает тест, я мог бы указать самостоятельно через Moq. - person Alex Dee; 30.04.2011
comment
Я не уверен, что могу сказать, что использование DI в тестировании - это плохо. Может быть, неоптимально;) Что вы хотите делать со своими тестами, так это удалить как можно больше внешних "вещей" и использовать только то, что вы тестируете. Если вы используете DI в своих тестах, теперь у вас есть дополнительная сложность для внедрения зависимостей. На этом этапе вы фактически тестируете свой DI, а также тестируемый объект. Возможно, вы сможете обосновать использование DI в своих тестах, хотя мне еще никогда не приходилось в этом нуждаться. При использовании DI ничего не должно быть тесно связано с чем-либо, включая DI, поэтому он вам не понадобится. - person Russell Troywest; 30.04.2011