I'm currently trying to implement a StopWatch
class. The interface is something like:
interface IStopWatch {
void Run();
void Stop();
int SecondsElapsed { get; }
int MinutesElapsed { get; }
}
Basically my app will need to use a StopWatch
, but for testing purposes it'd be nice to have a way of artifially modifing a StopWatch
es' results, so that is the reason I am making all my code reference an IStopWatch
instead of .NET's System.Stopwatch
.
As I'm trying to develop this Test-First, I'll have to make code for my StopWatch
class only after writing its tests. I already realized that the tests I'm going to do aren't going to be Unit-Tests, as I'm using .NET's System.Stopwatch
class internally.
So, in my undertanding, the only thing I can do now are tests that look like the following:
[TestMethod]
public void Right_After_Calling_Run_Elapsed_Minutes_Equals_Zero() {
IStopWatch stopWatch = new StopWatch();
stopWatch.Run();
Assert.AreEqual<int>(0, stopWatch.ElapsedMinutes);
}
[TestMethod]
public void One_Second_After_Run_Elapsed_Seconds_Equals_One() {
IStopWatch stopWatch = new StopWatch();
stopWatch.Run();
Thread.Sleep(1000 + 10);
Assert.AreEqual<int>(1, stopWatch.ElapsedSeconds);
}
[TestMethod]
public void Sixty_Seconds_After_Run_Elapsed_Minutes_Equals_One() {
IStopWatch stopWatch = new StopWatch();
stopWatch.Run();
Thread.Sleep(60 * 1000 + 1000);
Assert.AreEqual<int>(1, stopWatch.ElapsedMinutes);
}
I know I can't just run this as often as my Unit-Tests, but I think there is nothing I can do about this. Is my approach correct or am I missing something?
Thanks
Edit
So I ended up following both Quinn351 and Sjoerd's advices and coded something that uses DateTimes instead of .NET's Stopwatch class:
public class MyStopWatch : IMyStopWatch {
private DateTime? firstDateTime = null;
private DateTime? secondDateTime = null;
private bool isRunning = false;
public void Start() {
isRunning = true;
firstDateTime = DateTime.Now;
}
public void Stop() {
isRunning = false;
secondDateTime = DateTime.Now;
}
public void Reset() {
firstDateTime = null;
secondDateTime = null;
isRunning = false;
}
public TimeSpan GetTimeElapsed() {
return secondDateTime.Value.Subtract(firstDateTime.Value);
}
}
This allows me to make other implementations that have getter/setters for both dates so I can make GetTimeElapsed() return whatever I want.