2011-09-15 54 views
1

我有以下的方法,我想单元测试:单元测试时间差

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变量的正确值。

任何想法,将不胜感激。

回答

1

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

1

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

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

(又名“收集,然后用”从Mock-Eliminating Patterns。)

4

时钟的想法 - 这是可以获取当前时间 - 实际上是一个服务你根据。如果你依靠它明确通过一些接口(IClock)像你会任何其他服务。然后,您可以创建一个“生产”实现,该实现代表System.DateTime.UtcNowSystem.DateTime.Now以及虚假实现或模拟测试。

以我个人的经验来说,假设你可以设置,推进等等,而不是使用模拟框架来处理这个特定的场景 - 这是我见过并且使用了很多的技巧(这就是为什么野田时间用IClock接口和StubClock实现来支持它)。

+0

谢谢乔恩C#中,这是一个伟大的建议,我我一定会使用它。 –

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

以上是使用起订量