2014-03-04 3 views
5

xUnit.net을 사용하여 동일한 인터페이스의 여러 구현에 대해 동일한 테스트를 재사용 할 수있는 깨끗한 (읽기/이해할 수있는 ) 방법은 무엇입니까? (인터페이스의 모든 구현이 동일하게 동작하기로되어 있기 때문에)다른 구현에 대해 동일한 테스트를 재사용

내 시험의 행위어설 부분은 항상 동일합니다. 단지 SUT가 각 테스트 실행마다 다르며 일부 특정 테스트의 경우 배열 부분이 약간 다릅니다.

예를 들어 다음 인터페이스의 구현 (MemoryRepository, FileReposity ...)이 여러 개 있습니다.

// all implementations of IRepository must behave like this 
// so do this test for all implementations 
[Fact] 
public void GetRetrievesWhatWasPut() 
{ 
    IRepository sut = new MemoryRepository(); 
    sut.Set("key", 10); 
    var result = sut.Get("key"); 
    result.Should().Be(10); 
} 

답변

6

당신은 test classes as generic classes를 작성 고려할 수 :

public abstract class IntervalFacts<T> 
{ 
    [Theory, AutoCatalogData] 
    public void MinimumIsCorrect(IComparable<T> first, 
     IComparable<T> second) 
    { 
     var sut = new Interval<T>(first, second); 
     IComparable<T> result = sut.Minimum; 
     Assert.Equal(result, first); 
    } 
} 

public class DecimalIntervalFacts : IntervalFacts<decimal> { } 
public class StringIntervalFacts : IntervalFacts<string> { } 
public class DateTimeIntervalFacts : IntervalFacts<DateTime> { } 
public class TimSpanIntervalFacts : IntervalFacts<TimeSpan> { } 

이 특별한 예는 AutoFixture 년대를 활용

interface IRepository 
{ 
    object GetById(string id); 
    void Set(string id, object value); 
} 

은 이제 내 테스트는 모든 구현이 동일하게 동작한다는 보장되어 있습니다 구체적인 클래스를 구성하는 기능으로 각 T의 구체적인 인스턴스를 인스턴스화하는 번거 로움을 덜어줍니다.

정렬 단계를 다양하게하는 것은 어렵지만 다시해야 할 일에 따라 형식에 따라 생성 된 인스턴스가 자동으로 변경되도록 자동 고정 기능에 몇 가지 규칙을 도입 할 수 있습니다. 영업의 유형의


,이 같은 테스트를 작성할 수 있습니다 내가 아주 일반적인 테스트 클래스를 사용하는 방법을 볼 날이 SUT를 변경하는 데 도움이되지 않는

public abstract class RepositoryFacts<T> where T : IRepository 
{ 
    [Theory, AutoRepositoryData] 
    public void GetRetrievesWhatWasPut(T sut) 
    { 
     sut.Set("key", 10); 
     var result = sut.Get("key"); 
     result.Should().Be(10); 
    }   
} 

public class MemoryRepositoryFacts : RepositoryFacts<MemoryRepository> { } 
public class FileReposityRepositoryFacts : RepositoryFacts<FileReposity> { } 
+0

합니다. 귀하의 예는 SUT를 변화시키지 않습니다. – bitbonk

+0

하지만 그럴 수 있습니다; 'IComparable '대신'T'를 요구하십시오 ... –

+0

제가 일종의 오해가있을 수 있다고 생각합니다. 예를 들어 제 질문을 업데이트했습니다. SUT를 데이터 구동하기 위해'[Theory]'와'DataAttribute'를 어떻게 사용할 수 있는지 알고 있지만 generics 사용의 이점은 없습니다. – bitbonk

관련 문제