如何为以下代码块编写单元测试
public class Hotel
{
DateTime CLOSING_TIME // imported from somewhere else
public bool IsOpen
{
get
{
return DateTime.Now <= CLOSING_TIME
}
}
}
我尝试跟随其中任何一个都会一直失败,我如何确保两个单元测试用例每次都会通过:
[TestFixture]
public void ShouldBeOpen()
{
var Hot= new Hotel();
Assert.True(Hot.IsOpen);
}
[TestFixture]
public void ShouldBeOpen()
{
var Hot= new Hotel();
Assert.False(Hot.IsOpen);
}
有人可以帮忙吗?
答案 0 :(得分:2)
您的测试有很多问题:
DateTime
,而您无法在IsOpen
中表达出来我个人还认为,这种琐碎的测试是没有用的,因为它没有为该测试增加任何价值:
[TestFixture]
public void ShouldBeOpen()
{
Assert.True(DateTime.Now <= CLOSING_TIME);
}
不过,IsOpen
中的微小变化可以改善您的实施和测试代码,并使代码保持简单(无需存根/模拟系统日期):
public sealed class Hotel
{
public bool IsOpenAt(DateTime time) => time.TimeOfDay <= CLOSING_TIME.TimeOfDay;
}
通过这类测试可以真正测试一些业务断言:
[TestFixture]
public void ShouldBeOpen()
{
Assert.True(new Hotel().IsOpenAt(CLOSING_TIME));
}
[TestFixture]
public void ShouldNotBeOpen()
{
Assert.False(new Hotel().IsOpenAt(CLOSING_TIME.AddMinutes(1)));
}
尽管没有要求,但我想解决一些问题:CLOSING_TIME
。在我看来,该字段可疑。确实,我怀疑您设置此值的方式会导致某物与Hotel
的不必要耦合。如果不是这种情况,我建议您将这个值作为构造函数的参数来请求,以实现更好的去耦:
public sealed class Hotel
{
private readonly DateTime _closingTime;
public Hotel(DateTime closingTime) => _closingTime = closingTime;
public bool IsOpenAt(DateTime time) => time.TimeOfDay <= _closingTime.TimeOfDay;
}
答案 1 :(得分:0)
我将下面的代码组合在一起以模拟一个时间接口,您可以将其用于单元测试。使用此功能,您可以将时间设置为您指定的实时时间或虚假时间。在单元测试中,我经常使用这种方法。这称为依赖注入或构造函数注入,对单元测试非常有用。
class Hotel
{
public DateTime ClosingTime = DateTime.ParseExact("17:00:00", "HH:ii:ss", CultureInfo.InvariantCulture);
public IStubClock Clock;
public bool IsOpen
{
get
{
return Clock.Now.TimeOfDay <= ClosingTime.TimeOfDay;
}
}
public Hotel(IStubClock clock)
{
Clock = clock;
}
}
使用此接口,您可以模拟任何DateTime.Now结构
public interface IStubClock
{
DateTime Now { get; }
}
假的变体
public class FakeClock : IStubClock
{
private DateTime _now;
public DateTime Now
{
get
{
return _now;
}
}
public FakeClock(DateTime now)
{
_now = now;
}
}
还有一个真正的变体
public class RealClock : IStubClock
{
public DateTime Now
{
get
{
return DateTime.Now;
}
}
}
然后您可以在测试中使用它们
class Program
{
static void Main(string[] args)
{
IStubClock fakeClock = new FakeClock(new DateTime(1, 1, 1, 10, 0, 0)); //time is set to 10am
IStubClock realClock = new RealClock(); //time is set to whatever the time now is.
Hotel hotel1 = new Hotel(fakeClock); //using fake time
Hotel hotel2 = new Hotel(realClock); //using the real time
}
}