我必须测试一种方法,该方法在一段时间后执行一定量的工作。
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/