Reputation: 6597
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
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
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
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
Reputation: 22580
Can you make your Mock SystemTime
object increment it's value in the Now
Getter? That would make them different.
Upvotes: 1