C# 单元测试 - Thread.Sleep(x) - 如何模拟系统时钟

标签 c# unit-testing multithreading

我必须测试一种方法,该方法在一段时间后执行一定量的工作。

while (running)
{
    ...
    // Work
    ...
    Thread.Sleep(Interval);
}

Interval 作为参数传递给类,因此我可以只传递 0 或 1,但如果不是这种情况,我对如何模拟系统时钟很感兴趣。

在我的测试中,我希望能够简单地将时间向前设置 TimeSpan Interval 并唤醒线程。

我以前从未为作用于执行线程的代码编写过测试,我确信需要避免一些陷阱 - 请随时详细说明您使用的方法。

谢谢!

最佳答案

如果您不想测试线程实际上处于休眠状态这一事实,一种更直接的方法(也是一种可能的方法)是使用 ISleepService。然后您可以模拟它,然后在您的测试中不休眠,但有一个实现会在您的生产代码中导致 Thread.Sleep。

ISleepService sleepService = Container.Resolve<ISleepService>();

..

while (running)
{
    ...
    // Work
    ...
    sleepService.Sleep(Interval);
}

使用最小起订量的示例:

    public interface ISleepService
    {
        void Sleep(int interval);
    }

    [Test]
    public void Test()
    {
        const int Interval = 1000;

        Mock<ISleepService> sleepService = new Mock<ISleepService>();
        sleepService.Setup(s => s.Sleep(It.IsAny<int>()));
        _container.RegisterInstance(sleepService.Object);

        SomeClass someClass = _container.Resolve<SomeClass>();
        someClass.DoSomething(interval: Interval);

        //Do some asserting.

        //Optionally assert that sleep service was called
        sleepService.Verify(s => s.Sleep(Interval));
    }

    private class SomeClass
    {
        private readonly ISleepService _sleepService;

        public SomeClass(IUnityContainer container)
        {
            _sleepService = container.Resolve<ISleepService>();
        }

        public void DoSomething(int interval)
        {
            while (true)
            {
                _sleepService.Sleep(interval);
                break;
            }
        }
    }

更新

在设计\维护说明中,如果更改“SomeClass”的构造函数或向类的用户添加依赖注入(inject)点很痛苦,那么服务定位器类型模式可以在这里提供帮助,例如:

private class SomeClass
{
    private readonly ISleepService _sleepService;

    public SomeClass()
    {
        _sleepService = ServiceLocator.Container.Resolve<ISleepService>();
    }

    public void DoSomething(int interval)
    {
        while (true)
        {
            _sleepService.Sleep(interval);
            break;
        }
    }
}

关于C# 单元测试 - Thread.Sleep(x) - 如何模拟系统时钟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3398294/

相关文章:

java - 同步调用锁定条件的 signalAll() 时出现 IllegalMonitorStateException

c# - 在 WPF 中创建动态 CRUD UI

c# - 以编程方式检索多个类的静态成员

c# - 如何从 ViewModel (WPF) 引用 UI 元素?

c# - 是否可以模拟 .NET HttpWebResponse?

c++ - 检测 C++ 结构是从单元测试更新的

javascript - 在单元测试中使用 AudioContext

c# - AWS/SES 电子邮件发送...您的体验如何?

c# - Parallel.For 在这种情况下造成巨大的上下文切换开销......为什么?

java - 当所有线程完成处理时运行代码