2012-01-16 2 views
0

Я пытаюсь написать тест MSpec, который создает экземпляр одного из моих контроллеров со всеми правильными привязками Ninject. Как мне это сделать? Это то, что я до сих пор:Как я могу использовать Ninject в своих тестах MS MVC MS?

[Subject(Concern.Initialization)] 
public class when_permanent_employee_page_is_loaded_for_first_time 
{ 
    private static PermanentEmployeeController controller; 

    Establish context =() => 
     { 
      NinjectControllerFactory controllerFactory = new NinjectControllerFactory(); 
      ControllerBuilder.Current.SetControllerFactory(controllerFactory); 
      controller = (PermanentEmployeeController)controllerFactory.CreateController(new RequestContext(), "PermanentEmployee"); 
     }; 

    private Because of =() => controller.Index(); 

    private It should_load_all_available_jobs =() => 
     { 
      var blah = controller; 
      var blah3 = 3; 
     }; 
    It should_load_all_available_locations; 
    It should_load_all_available_departments; 
} 

В приведенном выше коде, я просто пытаюсь увидеть, если я могу создать экземпляр моего контроллера со всеми креплениями Ninject в такт. NinjectControllerFactory класс выглядит следующим образом:

public class NinjectControllerFactory : DefaultControllerFactory 
{ 
    private IKernel kernel = new StandardKernel(new DefaultModule()); 

    public IKernel Kernel 
    { 
     get 
     { 
      return kernel; 
     } 
     set 
     { 
      this.kernel = value; 
     } 
    } 

    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) 
    { 
     if (controllerType == null) 
     { 
      return null; 
     } 

     return (IController)kernel.Get(controllerType); 
    } 
} 

А класс DefaultModule так:

public class DefaultModule : NinjectModule 
{ 
    /// <summary> 
    /// Performs the binding of interfaces to their respective implementations. 'Tis very cool. 
    /// </summary> 
    public override void Load() 
    { 
     // Data service bindings 
     Bind<IJobService>().To<JobServiceImpl>().InTransientScope(); 
     Bind<IJobWsWrapper>().To<JobWsWrapperImpl>().InTransientScope(); 

     // View model factory bindings 
     Bind<IPermanentEmployeeViewModelFactory>().To<PermanentEmployeeViewModelFactoryImpl>().InTransientScope(); 
    } 
} 

Так что мой вопрос: есть ли способ определить привязки моего модуля Ninject в моем тесте MSpec и то мой экземпляр-контроллер использует эти привязки? Я хочу избежать создания экземпляра моего контроллера следующим образом: var controller = new Controller(), поскольку это не позволяет мне проверять привязки Ninject. Я также изучил класс TestControllerBuilder из библиотеки MvcContrib, но я не понял, как создавать экземпляры контроллеров с привязками Ninject к нему. Спасибо за помощь!

+2

Обычно вы должны избегать использования каких-либо контейнеров в своих модульных тестах. Вы должны подключить все зависимости, которые класс имеет вручную (возможно, путем извлечения проводки к заводским методам) или использовать насмешливую структуру (и снова реорганизовать создание такой вещи в заводском методе). – Steven

+0

Если у вас есть контроллеры с многочисленными зависимостями (запах!), Вы можете попытаться использовать автофокусные средства Machine.Fakes. –

+0

Спасибо за информацию ребята! Дело в том, что у меня уже есть модульные тесты, которые тестируют компоненты без DI. Тем не менее, я пытаюсь добавить тесты истории, которые проверяют всю историю пользователей, а также проверяют интеграцию различных частей с помощью DI. Я буду изучать автоматические устройства Machine.Fakes. Спасибо за подсказку :) – cbbcloud

ответ

1

Хорошо, я понял, как инициализировать мой контроллер вместе с Ninject Bindings в моих тестах MSpec! Ну, я не понял этого. Сотрудник сделал, но теперь это не имеет значения. Вот как это делается:

public class when_permanent_employee_page_is_loaded_for_first_time 
{ 
    private static Mock<IJobService> jobServiceMock; 
    private static Mock<IUtilsService> utilsServiceMock; 
    private static PermanentEmployeeController controller; 
    private static ContextMocks mocks; 

    private static IList<Job> jobs = new List<Job>(); 
    private static IList<string> departments = new List<string>(); 
    private static IList<string> locations = new List<string>(); 
    private static PermanentEmployeeJobsViewModel viewModel; 

    Establish context =() => 
     {  
      jobServiceMock = new Mock<IJobService>(); 
      jobServiceMock.Setup(x => x.GetJobs(1)).Returns(jobs); 
      jobServiceMock.Setup(x => x.GetDepartmentsFromJobs(jobs)).Returns(departments); 
      jobServiceMock.Setup(x => x.GetLocationsFromJobs(jobs)).Returns(locations); 

      utilsServiceMock = new Mock<IUtilsService>(); 

      var kernel = new StandardKernel(new DefaultModule()); 
      kernel.Rebind<IJobService>().ToConstant(jobServiceMock.Object); 
      kernel.Rebind<IUtilsService>().ToConstant(utilsServiceMock.Object); 

      controller = kernel.Get<PermanentEmployeeController>(); 
      mocks = new ContextMocks(controller); 
     }; 

    Because of =() => 
     { 
      PartialViewResult view = (PartialViewResult)controller.Index(); 
      viewModel = (PermanentEmployeeJobsViewModel)view.ViewData.Model; 
     }; 

    It should_load_all_available_jobs =() => 
     { 
      jobServiceMock.Verify(x => x.GetJobs(1)); 
      jobServiceMock.Verify(x => x.GetDepartmentsFromJobs(jobs)); 
      jobServiceMock.Verify(x => x.GetLocationsFromJobs(jobs)); 
      viewModel.Departments.ShouldEqual(departments); 
     }; 

    It should_load_all_available_locations; 
    It should_load_all_available_departments; 
} 

Хорошо, вот и все :). Надеюсь, кто-то может воспользоваться этим ответом. Особая благодарность моему коллеге за это. Вы знаете, кто вы: D

Смежные вопросы