不确定如何实现这一目标。我试图对一个等待几分钟的方法进行单元测试,请看这里:
internal class JctRestartViaSmsAttemptTestRunner : ITestRunner<JctRestartViaSmsAttempt>
{
private readonly IMayWantMonitoring _queues;
private readonly IAppSettings _appSettings;
public JctRestartViaSmsAttemptTestRunner(IMayWantMonitoring queues, IAppSettings appSettings)
{
_queues = queues;
_appSettings = appSettings;
}
public JctTest Execute(JctRestartViaSmsAttempt jctMessageType)
{
// after five minutes, publish an event to check if the JCT logged in
var jctLoggedInTimeOut = TimeSpan.FromMinutes(double.Parse(_appSettings["JctLogInTimeOut"]));
var message = new JctRestartViaSmsValidate(jctMessageType.Imei);
Task.Delay(jctLoggedInTimeOut)
.ContinueWith(x => _queues.Publish(message));
// reset test values
return new JctTest("6", jctMessageType.Imei, null, null, null);
}
}
这是我的测试方法,但我无法模拟任务延迟。
[Test]
public void TaskTest()
{
// arrange
var imei = _fixture.Create<string>();
_appSettings.Setup(c => c["JctLogInTimeOut"]).Returns("5");
var message = _fixture.Build<JctRestartViaSmsAttempt>()
.With(x => x.Imei, imei)
.Create();
var sut = _fixture.Create<JctRestartViaSmsAttemptTestRunner>();
// act
sut.Execute(message);
// assert
_queues.Verify(x => x.Publish(It.Is<JctRestartViaSmsValidate>(y => y.Imei == imei)));
}
这是引发的错误:
Moq.MockException:模拟上的预期调用至少一次, 但从未执行过:x =&gt; x.Publish(It.Is(y =&gt; y.Imei == .imei))没有 设置已配置。没有进行任何调用。在 Moq.Mock.ThrowVerifyException(MethodCall expected,IEnumerable
1 setups, IEnumerable
1 actualCalls,Expression expression,Times times, Int32 callCount)在Moq.Mock.VerifyCalls(拦截器 targetInterceptor,MethodCall expected,Expression expression,Times 时间)在Moq.Mock.Verify [T](模拟1 mock, Expression
1表达式, Moq.Mock1.Verify(Expression
1的时间,字符串failMessage) 表达)at JustEat.PrivateAPN.Worker.UnitTests.TestRunners.JctRestartViaSmsAttemptTestFixture.RunJctTest_WhenRestartAttemptSmsIsSent_ShouldPublishJctRestartValidateMessageWithTheRightImei() 在
我知道我需要自定义/配置我的灯具才能进入回调但是我不知道该怎么做,任何帮助都会非常感激
答案 0 :(得分:1)
你不应该在没有Task
的情况下解雇await
,以便在>> 时完成,其他事情可能会依赖于结果。
所以我建议你改为:
internal class JctRestartViaSmsAttemptTestRunner : ITestRunner<JctRestartViaSmsAttempt>
{
private readonly IMayWantMonitoring _queues;
private readonly IAppSettings _appSettings;
public JctRestartViaSmsAttemptTestRunner(IMayWantMonitoring queues, IAppSettings appSettings)
{
_queues = queues;
_appSettings = appSettings;
}
public async Task<JctTest> ExecuteAsync(JctRestartViaSmsAttempt jctMessageType)
{
// after five minutes, publish an event to check if the JCT logged in
var jctLoggedInTimeOut = TimeSpan.FromMinutes(double.Parse(_appSettings["JctLogInTimeOut"]));
var message = new JctRestartViaSmsValidate(jctMessageType.Imei);
// this will now delay in a non blocking fashion.
await Task.Delay(jctLoggedInTimeOut);
_queues.Publish(message);
// reset test values
return new JctTest("6", jctMessageType.Imei, null, null, null);
}
}
await
的另一个原因是你有这个_queues
如果你打算稍后阅读,你永远不能保证内容,因为线程池中可能仍然有一个线程处理Task.Delay
。
如果您无法更改方法的签名,那么您必须使用Thread.Sleep()
来阻止当前线程,直到它完成。
因为您确实指定了Task.Delay
我会假设您正在使用它来获取非阻止的好处。
如果您使用Thread.Sleep()
,可能需要考虑在JctRestartViaSmsAttemptTestRunner
中运行Task.Run()
,这样只会阻止正在运行的线程。
internal class JctRestartViaSmsAttemptTestRunner : ITestRunner<JctRestartViaSmsAttempt>
{
private readonly IMayWantMonitoring _queues;
private readonly IAppSettings _appSettings;
public JctRestartViaSmsAttemptTestRunner(IMayWantMonitoring queues, IAppSettings appSettings)
{
_queues = queues;
_appSettings = appSettings;
}
public JctTest Execute(JctRestartViaSmsAttempt jctMessageType)
{
// after five minutes, publish an event to check if the JCT logged in
var jctLoggedInTimeOut = TimeSpan.FromMinutes(double.Parse(_appSettings["JctLogInTimeOut"]));
var message = new JctRestartViaSmsValidate(jctMessageType.Imei);
Thread.Wait(jctLoggedInTimeOut.Milliseconds);
_queues.Publish(message);
// reset test values
return new JctTest("6", jctMessageType.Imei, null, null, null);
}
}
如果您有一个返回Task<>
的方法,那么如果您不能拥有.Result
测试方法签名,则必须使用async
。如果您以串行方式运行所有测试,那么这应该不是问题。如果您不知道为什么.Result
和.Wait()
读错了here
所以对于你的异步版本:
JctTest test = runner.ExecuteAsync().Result;
您的非异步版本保持不变。
答案 1 :(得分:0)
执行方法不是真正可测试的,因为它启动了延迟任务,但您无法从外部管理该任务。
所以,你可以尝试使用Thread.Sleep
,这不是很好但应该有效:
[Test]
public void TaskTest()
{
// arrange
var imei = _fixture.Create<string>();
_appSettings.Setup(c => c["JctLogInTimeOut"]).Returns("1");
var message = _fixture.Build<JctRestartViaSmsAttempt>()
.With(x => x.Imei, imei)
.Create();
var sut = _fixture.Create<JctRestartViaSmsAttemptTestRunner>();
// act
sut.Execute(message);
// verify the task was not executed yet
// ....
// let the test thread sleep and give the task some time to run
Thread.Sleep(2000);
// assert
_queues.Verify(x => x.Publish(It.Is<JctRestartViaSmsValidate>(y => y.Imei == imei)));
}
答案 2 :(得分:0)
我认为问题是允许测试完成。您在延迟启动后创建新任务但测试功能本身在此之前完成。
我对测试框架并不过分熟悉。但我希望你能在任务结束时使用.Wait()。这将创建一个阻塞任务,您的主测试线程将被阻止,直到延迟完成。