单元测试时间增量

时间:2011-09-15 16:53:52

标签: c# unit-testing mocking

我有以下方法,我想进行单元测试:

public void Upload(string identifier, Stream data)
{
    var startTime = SystemTime.Now;

    innerDataIntegrationInterface.Upload(identifier, data);

    var endTime = SystemTime.Now;

    TimeSpan totalUploadTime = endTime.Subtract(startTime);
    float transferRate = data.Length / (float)(totalUploadTime.Seconds + totalUploadTime.Milliseconds);

    m_log.Info(string.Format("Total uploading time for '{0}' was {1:00}.{2:000000} milliseconds transfered at {3} bytes/sec", identifier, totalUploadTime.Seconds, totalUploadTime.Milliseconds, transferRate));
}

基本上我已经注入了SystemTime对象,所以我可以在我的测试中设置它,但我无法弄清楚该做什么,以便startTime和endTime变量得到不同的值,所以我可以断言m_log.Info方法使用totalUploadTime和transferRate变量的正确值调用。

任何想法都会受到赞赏。

4 个答案:

答案 0 :(得分:4)

时钟的想法 - 有些东西可以获得当前时间 - 实际上是你依赖的服务。如果您通过某个接口(IClock)明确地依赖 ,就像您使用任何其他服务一样。然后,您可以创建一个“生产”实现,该实现委托给System.DateTime.UtcNowSystem.DateTime.Now以及假实现或模拟进行测试。

根据我的经验,值得假装你可以设置,推进等而不是使用模拟框架来实现这个特定场景 - 这是我见过的一种技术并且使用了很多(这就是Noda Time支持的原因)它带有IClock接口和StubClock实现。)

答案 1 :(得分:1)

你可以让你的Mock SystemTime对象在Now Getter中增加它的值吗?这会让他们与众不同。

答案 2 :(得分:1)

处理此问题的一种方法是将代码的复杂部分(您真正想要测试的部分)提取到另一个类或方法中并对其进行测试。

在这种情况下,这将涉及提取逻辑以将传输速率计算为一个单独的方法,该方法需要两个时间参数和传输的数量。

(又名,“Gather,Then Use”来自Mock-Eliminating Patterns。)

答案 3 :(得分:1)

如果innerDataIntegrationInterface.Upload是模拟界面的一部分,您可以模拟Upload方法,如:

var mock = new Mock<innerDataIntegrationInterface>();
mock.Setup(m => m.Upload(identifier, data)).Callback<object>(
    c =>
         {
          //increment SystemTime.Now
          //or call
          //Thread.Sleep(1); to sleep for microsecond
         });

以上是在c#中使用 Moq