2016-12-12 7 views
0

저는 ViewModel을 가지고 있습니다. ViewModel은 초기화 될 때 객체 목록을 생성합니다. 이러한 개체는 IoC에서 인터페이스 구현을 확인하여 만들어집니다.어떻게 테스트해야합니까?

뷰 모델

public class ApplianceViewModel : IAppliance 
    { 
     private List<IHardware> HardwareItems {get; set;} 

     public ApplianceViewModel() 
     { 
      HardwareItems = new List<IHardware>(); 
      var hardware1 = Constants.Kernel.Get<IHardware>(); 
      var hardware2 = Constants.Kernel.Get<IHardware>(); 

      HardwareItems.Add(hardware1); 
      HardwareItems.Add(hardware2);   
     } 
    } 

단위 테스트

[TestClass] 
public class ApplicanceViewModelTest 
{ 
    [TestMethod] 
    public void TestSomething() 
    { 
     //Arrange 
     var appliance = new ApplianceViewModel(); //This would fail to construct 

    } 
} 

kernel가 널이 될 것 같은 실패 상기 초기화. 기본적으로 상수 클래스를 사용하고 커널을 직접 액세스하는 것은 나쁜 설계라고합니다.

그러나 그렇다면 viewmodel의 생성자를 수정하여 목록을 초기화 할 수 있습니다. 다시 말해서 테스트 할 수 있습니까?

감사합니다.

+4

[service locator anti pattern] (http : //blog.ploeh.) 대신 DI와 함께 IoC를 사용하는 것이 더 좋지 않습니까?dk/2010/02/03/ServiceLocatorisanAnti-Pattern /)? – YuvShap

+0

@SomeUser : 네, ServiceLocator 패턴이 저를 해치는 것 같았습니다.하지만 내 마음 속의 질문은 그것을 다시 작성하는 방법 이었습니까? 그런 다음 문제를 해결할 것이라고 생각하는 [이 해결책] (http://stackoverflow.com/questions/7816769/injecting-an-ienumerable-into-a-constructor-with-a-inject-factory-method)을 발견했습니다. 나는 가지고있다. – Marshal

답변

0

다른 인터페이스 (예 : IHardwareStuff)를 사용하면 IHardware 개체의 목록을 반환 할 수 있습니다. IHardwareStuff은 ViewModel의 생성자에 인수로 전달됩니다. 의존성 주입 컨테이너에 의해 해결되고 원하는 경우 테스트 구현을 입력 할 수 있습니다.

이 분리를 수행하면 개체가 값 개체서비스 개체으로 분할됩니다. new을 수행하고 구체적인 값을 전달하여 처음 만드는 것. 후자는 의존성 주입 컨테이너에 의해 생성되며 생성자로 전달 된 구체적인 값을 갖지 않습니다.

두 개체 모두에 대해 단위 테스트를 작성할 수 있습니다.

0

생성자가 아무 것도 수행하지 않거나 유효성 검사 또는 변수 할당을 수행하는 것이 좋습니다.

나는 ApplianceViewModel의 생성자에 목록 HardwareItems을 주입 할 것을 제안합니다.

1

그렇다면 내가 목록을 초기화 할 수 있도록 내 viewmodel의 생성자를 수정하면 어떻게됩니까?

기존 상수 뷰 모델을 주입 할 수있는 런타임에 따라서
public class ApplianceViewModel : IAppliance 
{ 
    private List<IHardware> HardwareItems {get; set;} 

    public ApplianceViewModel(IHardware hardware1, Hardware hardware2) 
    { 
     HardwareItems = new List<IHardware>(); 
     var hardware1 = hardware1; 
     var hardware2 = hardware2; 

     HardwareItems.Add(hardware1); 
     HardwareItems.Add(hardware2);   
    } 
} 

:

당신은 IHardware 인터페이스의 구현으로 주입

var appliance = new ApplianceViewModel(Constants.Kernel.Get<IHardware>(), Constants.Kernel.Get<IHardware>()); 

... 그리고 당신의 유닛 테스트 프로젝트는 동일한 인터페이스의 다른 구현에서 전달합니다 :

IHardware testHardware = new TestHardware(); 
var appliance = new ApplianceViewModel(testHardware, testHardware); 

테스트를 통과하는 방식으로이 "TestHardware"클래스를 구현해야합니다. 조롱 프레임 워크를 사용하는 것이 유용 할 것입니다. 이에 대한 자세한 내용은 다음 링크를 참조하십시오. http://codetunnel.io/what-is-a-mocking-framework-why-is-it-useful/

+0

고마워요. 나는 무엇을해야할지 알았지 만 그것을하는 방법을 알지 못했다. 나는 내가해야 할 일을 [이] (http://stackoverflow.com/questions/7816769/injecting-an-ienumerable-into-a-constructor-with-a-ninject-factory-method)라고 생각한다. – Marshal