2012-01-16 2 views
0

모든 올바른 Ninject 바인딩을 사용하여 컨트롤러 중 하나를 인스턴스화하는 MSpec 테스트를 작성하려고합니다. 어떻게해야합니까? 위의 코드에서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에 모듈의 바인딩을 지정하는 방법이 있고 그런 다음 인스턴스화 된 컨트롤러에서 해당 바인딩을 사용합니까? 나는 이런 식으로 내 Controller를 인스턴스화하는 것을 피하고자한다 : var controller = new Controller()는 Ninject 바인딩을 테스트 할 수 없기 때문에 가능하다. 또한 MvcContrib 라이브러리에서 TestControllerBuilder 클래스를 살펴 보았지만 Ninject 바인딩을 사용하여 컨트롤러를 인스턴스화하는 방법을 알지 못했습니다. 도와 주셔서 감사합니다!

+2

일반적으로 단위 테스트에서 어떤 용기도 사용하지 않는 것이 좋습니다. 클래스가 수동으로 (공장 방법으로 배선을 추출하여) 모든 종속성을 연결하거나 조롱 프레임 워크를 사용해야합니다 (다시 팩터 리 방법에서 이러한 생성을 다시 작성해야합니다). – Steven

+0

많은 의존성 (냄새!)이있는 컨트롤러를 가지고 있다면 Machine.Fakes의 auto-focking 기능을 사용할 수 있습니다. –

+0

정보 주셔서 감사합니다! 문제는 이미 DI없이 구성 요소를 테스트하는 단위 테스트가 있다는 것입니다. 그러나 전체 사용자 스토리를 테스트하고 DI를 사용하여 여러 파트의 통합을 테스트하는 스토리 테스트를 추가하려고합니다. Machine.Fakes의 auto-focking 기능을 살펴볼 것입니다. 팁 주셔서 감사합니다 :) – cbbcloud

답변

1

Ok 나는 내 MSpec 테스트에서 Ninject Bindings와 함께 내 컨트롤러를 초기화하는 방법을 알아 냈습니다! 잘 나는 그것을 이해하지 않았다. 직장 동료가했지만 지금은 관련이 없습니다. 완료 방법은 다음과 같습니다.

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

관련 문제