2012-10-05 3 views
2

타이머 클래스를 만들고 있지만 테스트를 통과 할 수 없습니다. timer의 시간이 경과 할 때 메서드가 호출되는지 테스트하고 싶습니다. MOQ를 사용하여Moq를 사용하여 타이머 테스트

public class TimeOutTimer 
{ 
    private readonly ISubscriber _subscriber; 
    private Timer _timer; 

    public TimeOutTimer(ISubscriber subscriber) 
    { 
     _subscriber = subscriber; 
    } 

    public void Start() 
    { 
     _timer = new Timer(1000); 
     _timer.Start(); 
     _timer.Elapsed += TimerOnElapsed; 
    } 

    private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs) 
    { 
     _subscriber.TimeReached(); 
    } 
} 

그리고 시험 :

나는 다음과 같은 클래스가

[Test] 
public void Start_WithValidParameters_TriggersTimeReached() 
{ 
    var subscriberMock = new Mock<ISubscriber>(); 
    var timer = new TimeOutTimer(subscriberMock.Object); 

    timer.Start(); 

    subscriberMock.Verify(subscriber => subscriber.TimeReached()); 
} 

나는 타이머를 꺼내 _subscriber.TimeReached()에 직접 전화를 걸 경우를 공장.

내가 잘못 했나요?

+0

_subscriber.TimeReached()는 테스트를 통해 디버깅하는 경우에 들어갑니다. 구독자가 조롱을당한 이후로 추측하지는 않습니다. – Adam

+0

TimerOnElapsed가 호출되지 않습니다. 타이머가 작동하려면 어떻게 든 시험 대기해야합니까? Hmmmm ..... – Dante

+0

그러나 질문에 대한 응답으로 _subscriber.TimeReached()를 Elapsed 이벤트없이 직접 호출하면 예상대로 작동하고 Verify는 조롱 된 인터페이스 메서드에 대한 호출이 완료되었음을 확인합니다. – Dante

답변

4

예제에서 이벤트는 1000ms 후에 호출해야하지만 곧바로 확인해야합니다. 분명히 그 시점에서 이벤트를 호출 할 수 없습니다.

쉬운 방법은 테스트에 스레드를 넣는 것입니다.

[Test] 
public void Start_WithValidParameters_TriggersTimeReached() 
{ 
    var subscriberMock = new Mock<ISubscriber>(); 
    var timer = new TimeOutTimer(subscriberMock.Object);   

    timer.Start(); 
    Thread.Sleep(1000); 

    subscriberMock.Verify(subscriber => subscriber.TimeReached()); 
} 

그러나 이것은 시간 기반 클래스의 단위 테스트를 생성하는 올바른 방법은 아닙니다.

올바른 방법은 에 기반한 어댑터로 구현되는 ITimer 인터페이스를 만드는 것입니다.

그러면 ITimerTimeoutTimer의 종속성이되며 생성자 또는 속성으로 전달됩니다.

테스트에서 타이머를 모의 할 수 있으므로 대기없이 테스트와 동기화 할 수 있습니다 (예 : 클래스를 제어하여 수동으로 이벤트를 트리거 할 수 있음).

+0

더 많은 문제가 발생할 수 있음을 알고 있습니다. 대기 시간이 10 분이라면 10 분 동안 기다리는 단위 테스트를 실행할 수 없습니다. 더 나은 방법은 타이머를 삽입하는 것입니다. –

+0

@ AD.Net 두 번째 단락에서 내가 제안한 것입니다. 나는 너와 완전히 동의한다. – Sklivvz

+0

나는 그 때 올바른 길을 가고 있었다. 나는 수면을 추가했고 그것은 시험을 통과했다. "타이머를 기반으로하는 어댑터에 의해 구현 됨"은 다소 혼란 스럽습니다. 여기서는 어댑터 패턴을 언급 한 것 같습니다. 좀 더 우아한 방법으로 문제를 해결하기 위해 귀하의 제안을 시도하겠습니다. 도움에 감사드립니다! – Dante

2

글쎄, 여기서 비동기 작업을 다루고 있습니다. 핸들러에 중단 점을 넣고 코드를 통해 디버그 한 다음, 확인 행에서 맞춤법을 기다리는 경우 확인 행을 건너 뛸 때 핸들러가 실행되는 것을 볼 수 있습니다. 문제는 처리기가 발사하기 전에 테스트가 완료된다는 것입니다.

-1

테스트에서 Elapsed 이벤트를 발생시켜야합니다.

문제가되는 새로운 타이머라고 생각합니다. 그것을 주사 할 수있게 한 다음 시험에 주사하고 이벤트를 일으킬 수 있습니다.

관련 문제