简体   繁体   English

如何对心跳模式进行单元测试?

[英]How to unit test the heartbeat pattern?

I am writing a client which sends a "heartbeat signal" to the server every second. 我正在编写一个客户端,每秒向服务器发送一个“心跳信号”。 The client calls a WCF service in the background thread to report its activity. 客户端在后台线程中调用WCF服务以报告其活动。

How to unit test this? 如何对此进行单元测试? Do I need to wait for a couple of seconds and check if appropriate method was called several times? 我是否需要等待几秒钟并检查是否多次调用了适当的方法?

Should it be some sort of scenario test instead? 它应该是某种情景测试吗? Maybe I shouldn't be worried about calling the service continuously through the whole clients lifetime cycle? 也许我不应该担心在整个客户的整个生命周期中不断调用服务?

I can test a single call to WCF service but it doesn't test the "heartbeat pattern". 我可以测试对WCF服务的单个调用,但它不测试“心跳模式”。

I am using TDD approach. 我正在使用TDD方法。 (C#, NUnit, Moq) (C#,NUnit,Moq)

Any suggestions or examples? 有什么建议或例子吗?

EDIT: 编辑:

I think it wasn't clear enough. 我认为还不够清楚。

This is a much simpler version of what I have: 这是我所拥有的更简单的版本:

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();
   }
}

...and this is my test: ......这是我的考验:

[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));
}

I have a two questions: 我有两个问题:
1) Why my test always fails? 1)为什么我的测试总是失败? What I am doing wrong? 我做错了什么?
2) Should I test it at all? 2)我应该测试一下吗?

The functionality that you wish to test must be first isolated. 必须首先隔离要测试的功能。 For example in this case, there are a two aspects that could be tested. 例如,在这种情况下,可以测试两个方面。 One is that the hearbeat component actually sends a heartbeat message on the designated schedule. 一个是listenbeat组件实际上在指定的时间表上发送心跳消息。 The other is that the service receives the message. 另一个是服务接收消息。 If you abstract the service, then you can test the hearbeat component in isolation from the service implementation. 如果您抽象服务,那么您可以独立于服务实现测试听力组件。 This can be done in a unit test by starting the hearbeat component, then sleeping, then verifying that the expected number of messages were received by the stub or mock service implementation. 这可以在单元测试中通过启动听力组件然后休眠,然后验证存根或模拟服务实现接收到预期数量的消息来完成。 The test that ensures the service is receiving the message is an integration test and so is a not a "pure" unit test. 确保服务正在接收消息的测试集成测试 ,因此不是“纯”单元测试。 However, since it must be tested anyway, you can have a test case for this as well. 但是,由于必须进行测试,因此您也可以使用测试用例。

I would wrap the interaction with the service in a "gateway" type class. 我将在“网关”类型类中包装与服务的交互。 This can be replaced by a mock in your test, and the mock can count the calls that you make, or whatever statistics you might need. 这可以在测试中由模拟替换,模拟可以计算您所做的调用,或者您可能需要的任何统计信息。

Regards, Morten 此致,莫滕

The scenario you want to test is , strictly speaking, an integration test. 严格来说,您要测试的方案集成测试。

The approach I've taken to similar test-construction scenarios is to use this handy function: 我采用的类似测试构建方案的方法是使用这个方便的功能:

/// <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;
}

Usage: 用法:

// 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.");

It uses c# features only available since .Net4 but that probably suits most .Net developers these days. 它使用自.Net4以来仅提供的c#功能,但这可能适合大多数.Net开发人员。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM