2015-01-21 2 views
0

는 쉽게 설명 할 수 있도록 예측 가능한, 내가 코드MOQ 것은 사용하기 위해 호출됩니다

내가 FunctionA()가 기본 IAnother.DoAnotherJob()를 호출 할 때 확인하기 위해 단위 테스트 코드를 작성해야
public interface IAnother 
{ 
    void DoAnotherJob(DateTime date); 
} 

public class MainJob 
{ 
    private IAnother another; 

    public MainJob(IAnother another) 
    { 
     this.another = another; 
    } 

    public void FunctionA() 
    { 
     this.FunctionB(DateTime.Now); 
    } 

    public void FunctionB(DateTime date) 
    { 
     this.another.DoAnotherJob(date); 
    } 
} 

다음하지 특정 값을 확인합니다 현재 날짜 시간.

나는

[TestMethod()] 
    public void FunctionATest() 
    { 
     var mockAnother = new Mock<IAnother>(); 

     var mainJob = new MainJob(mockAnother.Object); 

     mainJob.FunctionA(); 

     mockAnother.Verify(x => x.DoAnotherJob(It.IsAny<DateTime>()), Times.Once); 
    } 

이 함수가 어떤 날짜 시간 호출되어 있는지 확인하는 테스트 코드를 작성할 수 있습니다,하지만 난 DateTime의 실제 값이 예측되지 않기 때문에 정확한 값을 지정하는 방법이 없습니다.

아이디어가 있으십니까?

+3

Roy Osherove는 [The Art of Unit Testing] (http://www.amazon.com/The-Art-Unit-Testing-examples/dp/1617290890) (페이지 134)에서 'SystemTime' 클래스는'.Now'와'.Now'가 반환하는 것을 설정하는 테스트 방법을 제공합니다. 거기에서 모든 것이 그 클래스를 대신 사용하는지 확인하는 것입니다. – chris

답변

2

DateTime.Now과 관련된 내용을 확인할 때 항상 어려움을 겪을 수 있습니다. 등록 정보 값은 통화간에 변경 될 가능성이 큽니다.

public interface ITimeProvider 
{ 
    DateTime Now { get; } 
} 

public class TimeProvider : ITimeProvider 
{ 
    DateTime Now { get { return DateTime.Now ; } } 
} 

어떤 당신이 다음 대신 직접 DateTime.Now의 사용합니다 :

mockAnother.Verify(x => x.DoAnotherJob(It.Is<DateTime>(d > DateTime.Now.AddSeconds(-1))), Times.Once); 

대안 당신이이 DateTime 해결하는 데 사용할 다른 클래스와 추상화를 소개하는 것입니다 : 당신이 할 수있는 최선의이 같은 것입니다 :

public class MainJob 
{ 
    private IAnother another; 
    private ITimeProvider timeProvider; 

    public MainJob(IAnother another, ITimeProvider timeProvider) 
    { 
     this.another = another; 
     this.timeProvider = timeProvider; 
    } 

    public void FunctionA() 
    { 
     this.FunctionB(this.timeProvider.Now); 
    } 

    public void FunctionB(DateTime date) 
    { 
     this.another.DoAnotherJob(date); 
    } 
} 

그런 다음, 당신의 단위 테스트가된다 :

,
[TestMethod()] 
public void FunctionATest() 
{ 
    var now = DateTime.Now; 
    var mockAnother = new Mock<IAnother>(); 
    var mockTimeProvider = new Mock<ITimeProvider>(); 
    mockTimeProvider.Setup(x => x.Now).Returns(now); 

    var mainJob = new MainJob(mockAnother.Object, mockTimeProvider.Object); 

    mainJob.FunctionA(); 

    mockAnother.Verify(x => x.DoAnotherJob(now), Times.Once); 
} 
+0

아주 좋은 대답입니다! –

+0

좋은 답변입니다. 나는 당신이 첫 번째 제안을 내 접근 방식으로 생각할 것입니다, 왜냐하면 저는 항상'DateTime.Now'를 다루기 위해 무언가를 소개하기에는 너무 무겁다 고 생각하기 때문에, 서버를 빌드 할 때 x 초 내에 테스트 케이스를 실행할만큼 충분히 빠르게 실행될 것입니다. . – hardywang

관련 문제