I’m not an expert on this, so I have posted what follows as a self -help and learning exercise for the two of us. This is my take on the problem.
As it stands, your changeMode
method is dependent upon three other classes, theDate
, theTime
and MessageBox
. It has a dual purpose, to return a string and, in certain circumstances, to display an error message. I’d remove the MessageBox
and do the error checking on the value returned from the method elsewhere. This would leave the changeMode
method with just one task to perform and, consequently, one task to be tested.
The method can be further refined by using a switch
statement in order both to remove multiple exit paths within the method and to have a single return statement at the end. It’s easier to debug when there is only one way out of a method.
To test the method, you need to create fake theDate
and fake theTime
classes. The creation of fake objects is facilitated by having them implement an Interface that they share with the class they are faking.
The showDate
method should return the same date on every occasion it is called and the showTime
method should return the same time on every occasion. This is because unit test should be self contained, exactly repeatable, run entirely in memory and be independent of external objects such as a database, system clock and random number generators. One final point, the States
variable is private. This needs to be protected in order to be able to access it for testing. The example below just has the one test but there needs to be a further two, testing for both StateValue=null
and StateValue=State.DisplayTime
namespace UnitTestProject1
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
public interface ITheTime
{
#region Public Methods and Operators
string ShowTime();
#endregion
}
public interface ITheDate
{
#region Public Methods and Operators
string ShowDate();
#endregion
}
public class ClockObject
{
#region Constants and Fields
protected States StateValue;
protected ITheDate theDate;
protected ITheTime theTime;
#endregion
#region Enums
protected enum States
{
DisplayDate,
DisplayTime
}
#endregion
#region Public Methods and Operators
public string changeMode()
{
string s;
switch (this.StateValue)
{
case States.DisplayDate:
{
s = this.theDate.ShowDate();
break;
}
case States.DisplayTime:
{
s = this.theTime.ShowTime();
break;
}
default:
{
s = null;
break;
}
}
return s;
}
#endregion
}
public class TheDateStub : ITheDate
{
#region Public Methods and Operators
public string ShowDate()
{
return "ShowDate";
}
#endregion
}
public class TheTimeStub : ITheTime
{
#region Public Methods and Operators
public string ShowTime()
{
return "ShowTime";
}
#endregion
}
[TestClass]
public class UnitTest1
{
#region Public Methods and Operators
[TestMethod]
public void changeModeReturnsDateStringWhenStateValueEqualsDisplayDate()
{
var mockClockObject = new MockClockObject();
string displayDate = mockClockObject.changeMode();
Assert.AreEqual(displayDate, "ShowDate");
}
#endregion
private class MockClockObject : ClockObject
{
#region Constructors and Destructors
public MockClockObject()
{
this.StateValue = States.DisplayDate;
this.theDate = new TheDateStub();
this.theTime = new TheTimeStub();
}
#endregion
}
}
}