2011-02-28 8 views
3

나는 매초 서버에 "하트 비트 신호"를 보내는 클라이언트를 작성하고 있습니다. 클라이언트는 백그라운드 스레드에서 WCF 서비스를 호출하여 해당 활동을보고합니다.하트 비트 패턴을 단위 테스트하는 방법?

단위 테스트 방법이 방법은? 몇 초 기다렸다가 적절한 방법이 여러 번 호출되었는지 확인해야합니까?

대신 시나리오 테스트일까요? 어쩌면 나는 전체 고객의 평생주기를 통해 지속적으로 서비스를 호출하는 것에 대해 걱정하지 않아도 될까요?

WCF 서비스에 대한 단일 호출을 테스트 할 수 있지만 "하트 비트 패턴"은 테스트하지 않습니다.

TDD 방식을 사용하고 있습니다. (C#, NUnit, Moq)

어떤 제안이나 예가 있습니까?

편집 : 나는 충분히 명확하지 생각

. 나는 두 가지 질문이

[Test] 
public void Heartbeat_called_twice_after_2_seconds() 
{ 
    var mockFeedService = new Mock<FeedService>(); 

    Thread.Sleep(2000); 
    mockFeedService.Verify(x => x.SendHeartBeat(), Times.AtLeast(2)); 
} 

:

이 내가 가진 무엇을 훨씬 간단 버전 :

public class FeedService 
{ 
    private Timer t; 

    public FeedService() 
    { 
     t.Interval = 1000; 
     t.Elapsed += TimerElapsed; 
     t.Start(); 
    } 

    private void TimerElapsed(object sender, ElapsedEventArgs e) 
    { 
     t.Stop(); 
     SendHeartbeat(); 
     t.Start(); 
    } 
} 

...이 내 테스트입니다
1) 왜 내 시험은 항상 실패합니까? 내가 뭘 잘못하고 있니?
2) 전혀 테스트해야합니까?

답변

5

테스트 할 기능을 먼저 격리해야합니다. 예를 들어이 경우 테스트 할 수있는 두 가지 측면이 있습니다. 하나는 청력 구성 요소가 실제로 지정된 일정에 하트 비트 메시지를 보내는 것입니다. 다른 하나는 서비스가 메시지를 수신한다는 것입니다. 서비스를 추출한 경우 서비스 구현과 별도로 고역 구성 요소를 테스트 할 수 있습니다. 이것은 고음 구성 요소를 시작한 다음 잠자는 방법으로 단위 테스트에서 수행 할 수 있습니다. 그런 다음 예상 개수의 메시지가 스텁 또는 모의 서비스 구현에 의해 수신되었는지 확인합니다. 서비스가 메시지를 수신하도록하는 테스트는 integration test이므로 "순수한"단위 테스트가 아닙니다. 그러나 어쨌든 테스트해야하므로이 경우에도 테스트 사례를 가질 수 있습니다.

+0

많은 감사. WCF 서비스가 메시지를 받는지는별로 신경 쓰지 않습니다. 내가 테스트해야 할 것은 오류를받지 않고 매 초마다 메시지를 보낸 내 클라이언트의 능력입니다. 나는 모의 서비스 (mock service)를 사용하여 WCF 서비스에 대한 '수동'호출을 테스트했지만 이것이 성취하고자하는 것은 아닙니다. "SendHeartbeat"메서드는 private이어야하며 TimerElapsed에서 호출되어야합니다. – Novitzky

2

서비스와의 상호 작용을 "게이트웨이"유형 클래스로 줄 것입니다. 이것은 테스트의 모의 (mock)로 대체 될 수 있으며, 모의 (mock)는 사용자가 작성한 호출 또는 필요한 통계를 셀 수 있습니다.

감사합니다, 모르 텐

+0

명확하게; 이 솔루션은 파트 refac (랩핑), 파트 테스트, 파트 모의이지만 테스트하기 쉬운 솔루션을 사용하면 강력한 디자인이 될 수 있습니다. – Morten

0

당신이 을 테스트 할 시나리오는 엄밀히 말하면, 통합 테스트입니다.

나는 유사한 테스트 건설 시나리오에 찍은 접근이 편리한 기능을 사용하는 것입니다

사용
/// <summary> 
/// Wait no longer than @waitNoLongerThanMillis for @thatWhatWeAreWaitingFor to return true. 
/// Tests every second for the 
/// </summary> 
/// <param name="thatWhatWeAreWaitingFor">Function that when evaluated returns true if the state we are waiting for has been reached.</param> 
/// <param name="waitNoLongerThanMillis">Max time to wait in milliseconds</param> 
/// <param name="checkEveryMillis">How often to check for @thatWhatWeAreWaitingFor</param> 
/// <returns></returns> 
private bool WaitFor(Func<bool> thatWhatWeAreWaitingFor, int checkEveryMillis, int waitNoLongerThanMillis) 
{ 
    var waitedFor = 0; 
    while (waitedFor < waitNoLongerThanMillis) 
    { 
     if (thatWhatWeAreWaitingFor()) return true; 

     Console.WriteLine("Waiting another {0}ms for a situation to occur. Giving up in {1}ms ...", checkEveryMillis, (waitNoLongerThanMillis - waitedFor)); 
     Thread.Sleep(checkEveryMillis); 
     waitedFor += checkEveryMillis; 
    } 
    return false; 
} 

:

// WaitFor (transaction to become failed, checkEverySoOften, waitNoLongerThan) 
int wait = (Settings.EventHandlerCoordinatorNoActivitySleepTime + 5) * 1000; 
var failedEventExists = WaitFor(() => EventQueueManager.GetFailedEvents(0, 10).TotalRecords > 0, checkEveryMillis: 1000, waitNoLongerThanMillis: wait); 

if (!failedEventExists) 
    Assert.Fail("Waited longer than " + wait + " without any evidence of the event having been handled. Expected to failed event on the queue."); 

그것은 C# .NET을 사용하여이 .Net4하지만 이후에만 사용할 수 있습니다 요즘 대부분의 .NET 개발자에게 적합 할 것입니다.

관련 문제