Let’s assume we have a class like the DateTimeHelper class shown below, that has a dependency to the DateTime object and we want to write a test for it. It’s untestable. All you can do is run your test every hour. But i think this is actually not a best practice. By the way it is not reproduceable and we are not able to run a test like this on a continuous integration Server. We Need to get control over the time!

See the DateTimeHelper class:

public static class DateTimeHelper
{
    /// <summary>
    /// Returns an text according to the current time
    /// </summary>
    /// <returns></returns>
    /// <remarks>
    /// Uhrzeiten die unterschieden werden sollen:
    /// <list type="bullet">
    /// <item>23-6: night</item>
    /// <item>7-10: morning</item>
    /// <item>11-13: noon</item>
    /// <item>14-22: evening</item>
    /// </list>
    /// </remarks>
    public static string GetTextForCurrentDate()
    { 
        // Dependency to the DateTime Object
        // Will always return the current time
        DateTime currentTime = DateTime.Now;
 
        if (currentTime.Hour >= 23 || currentTime.Hour <= 6)
        {
            return "night";
        }
        if (currentTime.Hour >= 7 && currentTime.Hour <= 10)
        {
            return "morning";
        }
        if (currentTime.Hour >= 11 && currentTime.Hour <= 13)
        {
            return "noon";
        }
        if (currentTime.Hour >= 14 && currentTime.Hour <= 22)
        {
            return "evening";
        }
 
        throw new NotImplementedException("This sould never happen");
    }
}

But wait! There is Typemock Isolator a tool that let’s you fake / mock any dependency! With Typemock we are also able to take control over the DateTime object!

In an earlier article (working sample data driven RowTest with MSTest) i explained how to do a RowTest.
The magic happens in Line 31: When DateTime.Now is called, it should return a date we have defined. Now we have the possibility to walk through all our code paths! Amazing!

The full DateTimeHelperTest class:

[TestClass, Isolated(DesignMode.Pragmatic)]
public class DateTimeHelperTest
{
    private TestContext testContextInstance;
    public TestContext TestContext
    {
        get { return testContextInstance; }
        set { testContextInstance = value; }
    }
 
    /// <summary>
    /// A test for GetImageForCurrentTime
    ///</summary>
    [TestMethod()]
    [DeploymentItem("BusinessLogic.Test\\TestData\\GetImageForCurrentTime_TestBoundaries.xml")]
    [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\GetImageForCurrentTime_TestBoundaries.xml", "Row", DataAccessMethod.Sequential)]
    public void GetTextForCurrentDateTest()
    {
        int hourToTest = Int32.Parse((string)TestContext.DataRow["HourToTest"]);
        string assertValue = (string)TestContext.DataRow["AssertValue"];
 
        Execute_GetTextForCurrentDateTest(hourToTest, assertValue);
    }
 
    private void Execute_GetTextForCurrentDateTest(int hourToTest, string assertValue)
    {
        string expected = assertValue;
        // If DateTime.Now is called, our DateTime wil be returned
        DateTime controlledDate = new DateTime(2013, 1, 1, hourToTest, 0, 0);
        // This is very the Typemock magic happens!
        Isolate.WhenCalled(() => DateTime.Now).WillReturn(controlledDate);
 
        string actual = DateTimeHelper.GetTextForCurrentDate();
 
        Assert.AreEqual(expected, actual);
    }
}

This is the XML File with all the neccessary test data. In my opinion it is the easiest way to simply test any hour that can occur.

<?xml version="1.0" encoding="utf-8" ?>
<Rows>
  <Row>
    <HourToTest>0</HourToTest>
    <AssertValue>night</AssertValue>
  </Row>
  <Row>
    <HourToTest>1</HourToTest>
    <AssertValue>night</AssertValue>
  </Row>
  <Row>
    <HourToTest>2</HourToTest>
    <AssertValue>night</AssertValue>
  </Row>
  <Row>
    <HourToTest>3</HourToTest>
    <AssertValue>night</AssertValue>
  </Row>
  <Row>
    <HourToTest>4</HourToTest>
    <AssertValue>night</AssertValue>
  </Row>
  <Row>
    <HourToTest>5</HourToTest>
    <AssertValue>night</AssertValue>
  </Row>
  <Row>
    <HourToTest>6</HourToTest>
    <AssertValue>night</AssertValue>
  </Row>
  <Row>
    <HourToTest>7</HourToTest>
    <AssertValue>morning</AssertValue>
  </Row>
  <Row>
    <HourToTest>8</HourToTest>
    <AssertValue>morning</AssertValue>
  </Row>
  <Row>
    <HourToTest>9</HourToTest>
    <AssertValue>morning</AssertValue>
  </Row>
  <Row>
    <HourToTest>10</HourToTest>
    <AssertValue>morning</AssertValue>
  </Row>
  <Row>
    <HourToTest>11</HourToTest>
    <AssertValue>noon</AssertValue>
  </Row>
  <Row>
    <HourToTest>12</HourToTest>
    <AssertValue>noon</AssertValue>
  </Row>
  <Row>
    <HourToTest>13</HourToTest>
    <AssertValue>noon</AssertValue>
  </Row>
  <Row>
    <HourToTest>14</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>15</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>16</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>17</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>18</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>19</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>20</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>21</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>22</HourToTest>
    <AssertValue>evening</AssertValue>
  </Row>
  <Row>
    <HourToTest>23</HourToTest>
    <AssertValue>night</AssertValue>
  </Row>
</Rows>

Related Resources

Further Reading