为了账号安全,请及时绑定邮箱和手机立即绑定

具有 sytem.DateTime 值的属性的单元测试 C#

具有 sytem.DateTime 值的属性的单元测试 C#

C#
富国沪深 2021-10-31 19:32:23
如何为以下代码块编写单元测试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); }有人可以帮忙吗?
查看完整描述

2 回答

?
慕标琳琳

TA贡献1830条经验 获得超9个赞

你的测试有很多问题:

  • 它们是不确定的(正如您已经注意到的),因为它们依赖于时间

  • 它们是多余的(第二次测试与第一次测试完全相同)

  • 从您输入的语义来看,您似乎需要处理时间而不是完整的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;

}


查看完整回答
反对 回复 2021-10-31
?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

我将下面的代码放在一起模拟一个可用于单元测试的时间接口。使用它,您可以将时间设置为您指定的实时时间或假时间。我在单元测试时经常使用这种方法。它被称为依赖注入或构造函数注入,这对于单元测试非常有用。


    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

        }

    }


查看完整回答
反对 回复 2021-10-31
  • 2 回答
  • 0 关注
  • 176 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信