2012-01-16 42 views
0

我想写一个MSpec测试,用我所有的正确Ninject绑定实例化我的控制器之一。我该如何去做呢?这是我到目前为止有:如何在我的ASP MVC MSpec测试中使用Ninject?

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

所以我的问题是:是否有在我MSpec测试指定我Ninject模块的绑定方式和那么我的实例化控制器使用这些绑定?我想避免像这样实例化我的控制器:var controller = new Controller(),因为这不允许我测试Ninject绑定。我也从MvcContrib库中查看了TestControllerBuilder类,但我还没有想出如何使用Ninject绑定实例化控制器。谢谢您的帮助!

+2

你通常应该尽量避免在单元测试中使用任何容器。你应该手动连接一个类的所有依赖关系(可能通过提取工厂方法的接线)或使用一个模拟框架(并再次在工厂方法中重构此类事物的创建)。 – Steven 2012-01-16 11:39:55

+0

如果你的控制器有很多依赖性(一种气味!),你可以尝试使用Machine.Fakes的自动设置功能。 – 2012-01-16 13:47:50

+0

感谢信息家伙!事情是,我已经有了单元测试,可以在没有DI的情况下测试组件。但是,我试图添加故事测试来测试整个用户故事,并使用DI测试不同部分的集成。我会研究Machine.Fakes的自动设备。谢谢你的提示:) – cbbcloud 2012-01-23 08:12:54

回答

1

好吧我想出了如何初始化我的控制器以及我的MSpec测试中的Ninject绑定!那么我没有弄明白。一位同事做到了,但现在无关紧要。这是它是如何完成的:

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