Sergio Romero
Sergio Romero

Reputation: 6597

Unit testing a time delta

I have the following method that I would like to unit test:

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

Basically I am already injecting the SystemTime object so I can set it up in my test but I can't figure out what to do so that the startTime and endTime variables get different values so I can assert that the m_log.Info method gets called with the correct values for the totalUploadTime and transferRate variables.

Any ideas would be appreciated.

Upvotes: 1

Views: 1231

Answers (4)

Jeff Sternal
Jeff Sternal

Reputation: 48583

One way to handle this is to extract the complicated part of your code (the portion you really want to test) into another class or method and test that.

In this case, that would involve extracting the logic to calculate the transfer rate into a separate method that takes two time parameters and the amount transferred.

(aka, "Gather, Then Use" from Mock-Eliminating Patterns.)

Upvotes: 1

Paul
Paul

Reputation: 1875

If innerDataIntegrationInterface.Upload is a part of mocked interface you can mock the Upload method like:

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

The above is in c# using Moq

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500465

The idea of a clock - something can get the current time - is effectively a service you're depending on. If you depend on it explicitly via some interface (IClock) like you would any other service. You can then create a "production" implementation which delegates to System.DateTime.UtcNow or System.DateTime.Now and a fake implementation or a mock for testing.

Personally in my experience it's worth having a fake that you can set, advance etc rather than using a mock framework for this particular scenario - it's a technique I've seen and used myself quite a bit (which is why Noda Time supports it with the IClock interface and a StubClock implementation).

Upvotes: 4

skaz
skaz

Reputation: 22580

Can you make your Mock SystemTime object increment it's value in the Now Getter? That would make them different.

Upvotes: 1

Related Questions