在使用 Moq 进行单元测试时避免在代码中使用 thread.sleep
Avoiding thread.sleep in code while unit testing with Moq
我有多个 thread.sleep 方法,有时会持续 20 秒。这是业务需求。我正在尝试通过模拟和跳过这些睡眠来对这些方法进行单元测试,以便测试可以 运行 更快并且实际上不会等待 20 秒。使用最小起订量框架。
感谢任何关于如何实现这一点的想法。
您实际上可以为 Thread.sleep 方法引入接口,并且您可以在编写 UT 时进行模拟
public interface IThreadSleep
{
void Sleep(int milliSec);
}
你可以有实现,像这样
public class ThreadSleep : IThreadSleep
{
public void Sleep(int milliSec)
{
Thread.Sleep(milliSec);
}
}
在你的业务中class,只需注入这个接口,然后你就可以模拟Thread.sleep
public class Class1
{
IThreadSleep _threadSleep;
public Class1(IThreadSleep threadSleep)
{
_threadSleep = threadSleep;
}
public void SomeMethod()
{
//
_threadSleep.Sleep(100);
}
}
希望这对您有所帮助。
不知道您拥有的实际代码,但至少知道一些想法。您可以将 Thread.Sleep
包装到 interface
中,然后将其注入您的业务 handler\controller。在实际实现中使用 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
可能无法模拟 Thread.Sleep
,因为它是一个静态方法,无法使用基于 DynamicProxy 的模拟框架(如 moq)模拟这些方法。
一种选择是使用基于 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 并在生产代码中通过真正的实现
我有多个 thread.sleep 方法,有时会持续 20 秒。这是业务需求。我正在尝试通过模拟和跳过这些睡眠来对这些方法进行单元测试,以便测试可以 运行 更快并且实际上不会等待 20 秒。使用最小起订量框架。 感谢任何关于如何实现这一点的想法。
您实际上可以为 Thread.sleep 方法引入接口,并且您可以在编写 UT 时进行模拟
public interface IThreadSleep
{
void Sleep(int milliSec);
}
你可以有实现,像这样
public class ThreadSleep : IThreadSleep
{
public void Sleep(int milliSec)
{
Thread.Sleep(milliSec);
}
}
在你的业务中class,只需注入这个接口,然后你就可以模拟Thread.sleep
public class Class1
{
IThreadSleep _threadSleep;
public Class1(IThreadSleep threadSleep)
{
_threadSleep = threadSleep;
}
public void SomeMethod()
{
//
_threadSleep.Sleep(100);
}
}
希望这对您有所帮助。
不知道您拥有的实际代码,但至少知道一些想法。您可以将 Thread.Sleep
包装到 interface
中,然后将其注入您的业务 handler\controller。在实际实现中使用 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
可能无法模拟 Thread.Sleep
,因为它是一个静态方法,无法使用基于 DynamicProxy 的模拟框架(如 moq)模拟这些方法。
一种选择是使用基于 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 并在生产代码中通过真正的实现