2009-10-28 8 views
2

런타임에 주입되는 ctor에서 여러 매개 변수를 사용하는 컨트롤러 클래스가 있습니다.TDD, 조롱, 의존성 주입 및 DRY 원칙

예 :

public ProductController(IProductRepositort productRepository, 
IShippingService shippingService, IEmailProvider emailProvider) 
    { 
    ... 
    } 

나는 시험 방법이 거대한지고 있음을 발견하고있다.

[Test] 
public void CanSendProduct() 
{ 
    //Code to set up stub 
       List<Product> products = new List<Product>(); 
       for (int i = 0; i < length; i++) 
       { 
        products.Add(new Product())); 
       } 

       var mockProductRepository = new Mock<IProductRepository>(); 
       mockProductRepository.Setup(x => x.GetProducts()).Returns(products); 

       //Code to set up stub 
       .... 
       .... 
       var mockShippingService = new Mock<IShippingService>(); 
       mockShippingService.Setup(x => x.GetShippers()).Returns(shippers); 

       //Code to set up stub 
       ..... 
       ..... 
       var mockEmailProvider = new Mock<IEmailProvider>(); 
       mockEmailProvider.Setup(x => x.Send()).Returns(provider); 

       //Execute Test 
       .... 
       .... 

       //Assert 
       .... 
       .... 
} 

물론, 그것은 실용적이지이 테스트 클래스의 모든 메소드에 모의 설치를 반복 다음과 같이 나는 방법을 설정하고있다.

내가 할 수있는 풍부한 mocking 개체를 만들려면 어떻게해야합니까? 동작 테스트의 확인과 동시에 설치의 고통을 최소화 하시겠습니까?

이 문제를 해결하기위한 TDD 모범 사례는 무엇입니까?

감사합니다.

답변

6

테스트 프레임 워크가 각 테스트 전후에 호출 될 setup/teardown 기능을 지원하는 경우 해당 기능의 일부 "기본"모의 객체를 만들고 파괴하십시오. 당신의 테스트는 그것들을 간단히 사용할 수 있으며, 기본 모의 객체가 당신을 위해 작동하지 않는 특별한 경우에, 그것들을 무시하고 그 테스트 내에서 로컬 mock 객체를 생성하기 만하면됩니다.

+1

+1. 또한 복잡한 테스트는 흔히 단일 클래스가 너무 많이하고 있음을 나타내는 기호입니다. 특히 "컨트롤러"와 같은 이름이 "관리자"와 비슷합니다. Inversion of Control 원리를 찾아보십시오. 또한 각 논리적 동작에 객체에 대한 단일 호출을 만들어 봅니다. 따라서 Add를 여러 번 호출하는 대신 하나의 목록을 가져올 수 있습니다. – kyoryu

0

행동 또는 기능 테스트 제품군을 사용하십시오. C# 또는 Java에서 사용하는 것처럼 보입니까? 어느 쪽이든 나는 FItnesse을 추천 할 것이지만 다른 것들도 있습니다. 단위 테스트에 관해서는 Winsor/Castle 또는 Spring과 같은 IOC 컨테이너를 사용하고, 실제 객체가 아닌 Mocks로 채워진 테스트 용 컨테이너를 설정할 수 있습니다.

(당신의 모의 프레임 워크는 필요에 따라,의 모의 공장을 통과 서명을 변경해야하는 경우) 난 그냥 방법으로이 코드를 추출하는 것
+0

IOC 컨테이너에 대해 들었지만 이것은 인터페이스 구현을 구체적으로 설정해야한다는 것을 의미합니다 ... Concrete imp (메모리 가짜가 될 것인가)을 사용하여 볼 수있는 유일한 문제는 그것이 될 것입니다 유지 보수의 악몽. 특히 시험 횟수가 늘어날 때. –

0

:

private Mock<IProductRepository> SetupStandardMockProductRepository() { 
    List<Product> products = new List<Product>(); 
    for (int i = 0; i < length; i++) { 
     products.Add(new Product())); 
    }  
    var mockProductRepository = new Mock<IProductRepository>(); 
    mockProductRepository.Setup(x => x.GetProducts()).Returns(products); 
} 

// ... and so forth 

그런 다음 테스트에서 :

var mockProductRepository = SetupStandardMockProductRepository(); 

// or make these static properties of some central test class, like this: 
var mockProductRepository = Stubs.StandardProductRepository;