I use VS2008 targetting .NET 2.0 Framework, and, just in case, no I can't change this :)
I have a DateCalculator
class. Its method GetNextExpirationDate
attempts to determine the next expiration, internally using DateTime.Today
as a baseline date.
As I was writing unit tests, I realized that I wanted to test GetNextExpirationDate
for different 'today' dates.
What's the best way to do this? Here are some alternatives I've considered:
baselineDate
and only use it from the unit test. In actual client code, disregard the property/overloaded method in favour of the method that defaults baselineDate
to DateTime.Today
. I'm reluctant to do this as it makes the public interface of the DateCalculator class awkward.baselineDate
that is internally set to DateTime.Today
. When testing, derive a DateCalculatorForTesting
from DateCalculator
and set baslineDate
via the constructor. It keeps the public interface clean, but still isn't great - baselineDate
was made protected and a derived class is required, both solely for testing.ExtensionAttribute
, then realized it wouldn't work because extension methods can't access private/protected variables. I initially thought this was really quite an elegant solution. :(I'd be interested in hearing what others think.
You can use an interface that supplies the baseline date. Normally you would use an implementation that returns DateTime.Today but for testing purposes have one that lets your unit tests supply a date.
This could also be useful if it becomes necessary to use the current date on a datebase server or some other machine that is not necessarily where your code is running.
In fact, here's the same question with some more detailed answers than mine: Unit Testing: DateTime.Now
I usually collect calls to the OS inside an abstraction/interface so that I can easily test it.. Just as Andrew as mentioned above.
However given only the need mentioned in the question; I feel 'Subclass and Override' is the simplest and least invasive way to get this done - Option 2 that the OP mentioned.
public class DateCalculator
{
public DateTime GetNextExpirationDate() { // call to GetBaseLineDate() to determine result }
virtual protected GetBaseLineDate() { return DateTime.Today; }
}
// in your test assembly
public class DateCalcWithSettableBaseLine : DateCalculator
{
public DateTime BaseLine { get; set;}
override protected GetBaseLineDate()
{ return this.BaseLine; }
}
One option is to create an internal overload which takes a DateTime, and delegate the real implementation to that:
public DateTime GetNextExpirationDate()
{
return GetNextExpirationDate(DateTime.Today);
}
internal DateTime GetNextExpirationDate(DateTime after)
{
// implementation goes here
}
You can then use InternalsVisibleToAttribute to make the overload visible to your test assembly, and your test assembly can then call it with DateTime values of its own choosing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With