我有多个方法,它们具有多个thread.sleep,有时可持续20秒。这是一项业务要求。我试图通过模拟和跳过这些睡眠来对这些方法进行单元测试,以便测试可以运行得更快,并且实际上不需要等待20秒。使用moq框架。 感谢有关如何实现此目标的任何想法。
答案 0 :(得分:1)
您实际上可以为Thread.sleep方法引入接口,并且可以在编写UT时进行模拟
public interface IThreadSleep
{
void Sleep(int milliSec);
}
您可以实现
public class ThreadSleep : IThreadSleep
{
public void Sleep(int milliSec)
{
Thread.Sleep(milliSec);
}
}
在您的业务类中,只需注入此接口,然后您就可以模拟Thread.sleep
public class Class1
{
IThreadSleep _threadSleep;
public Class1(IThreadSleep threadSleep)
{
_threadSleep = threadSleep;
}
public void SomeMethod()
{
//
_threadSleep.Sleep(100);
}
}
希望这会有所帮助。
答案 1 :(得分:1)
可能没有办法模拟Thread.Sleep
,因为它是静态方法,并且无法使用基于Moq的基于DynamicProxy的模拟框架进行模拟。
一种选择是使用基于Profiler API的工具,例如Microsoft Fakes(仅在VS Enterprise中)或Typemoq Professional。
更好的选择是不要在业务逻辑中直接调用Thread.Sleep
。相反,您可以做的是引入这样的接口
public interface ISleepService
{
void Sleep(int ms);
}
然后创建您在代码中使用的默认实现:
public class SleepService: ISleepService
{
public void Sleep(int ms)
{
Thread.Sleep(ms);
}
}
将ISleepService的依赖项添加到您的业务逻辑
public class MyBusinessLogic()
{
private ISleepService _sleepService;
public MyBusinessLogic(ISleepService sleepService)
{
_sleepService = sleepSerivce;
}
public void MyBusinessMethod()
{
// your code
_sleeService.Sleep(20000);
// more code
}
}
然后您可以在单元测试中轻松模拟ISleepService并在生产代码中传递真实的实现
答案 2 :(得分:0)
不知道您拥有的实际代码,但至少有一些想法。您可以将Thread.Sleep
包装到interface
中,然后将其注入到业务处理程序\控制器中。在实际的实现中,使用Thread.Sleep
来实际等待,但在测试中模拟interface
来避免Thread.Sleep
。例如:
public interface IMySleepContext
{
void Sleep(int milliseconds);
}
public class MySleepContext : IMySleepContext
{
public void Sleep(int milliseconds)
{
Thread.Sleep(milliseconds);
}
}
public class MyController
{
private readonly IMySleepContext _mySleepContext;
public MyController(IMySleepContext mySleepContext)
{
_mySleepContext = mySleepContext;
}
public void MyMethod()
{
//do something
_mySleepContext.Sleep(20000);
//do somethign
}
}
测试:
//Arrange
MyController mc = new MyController(Mock.Of<IMySleepContext>());
//Act
mc.MyMethod();
//Assert
//do assert