C# - 测试断言组件超时X秒后
问题描述:
假设我有一个简单的API类像这样,在外部调用时,但如果它没有完成的例外是5秒钟后抛出:C# - 测试断言组件超时X秒后
public class Api
{
private readonly IConnector connector;
public Api(IConnector connector)
{
this.connector = connector;
}
public string GetSomething()
{
var timer = new System.Timers.Timer(5000);
timer.Elapsed += TimeOut;
timer.Start();
//some external call which takes time
connector.Retrieve();
timer.Stop();
return "Something";
}
private void TimeOut(object sender, ElapsedEventArgs e)
{
throw new TimeoutException("Timed out!");
}
}
使用NUnit或其他方法,我该如何去测试上述请求需要8秒时抛出异常,但当请求需要3秒时成功?
我已经试过以下:
[TestFixture]
public class ApiTests
{
IConnector mockConnector;
Api api;
[SetUp]
public void Setup()
{
mockConnector = MockRepository.GenerateMock<IConnector>();
api = new Api(mockConnector);
}
[Test]
public void Api_RetrieveTakes3Seconds_SomethingReturned()
{
mockConnector.Stub(c => c.Retrieve()).Return(Task.Delay(3000).ContinueWith(c => "Something").Result);
var response = api.GetSomething();
Assert.AreEqual("Something", response);
}
[Test]
public void Api_RetrieveTakes8Seconds_TimeOutExceptionThrown()
{
mockConnector.Stub(c => c.Retrieve()).Return(Task.Delay(8000).ContinueWith(c => "Something").Result);
var response = api.GetSomething();
//assert an exception is thrown on the above
}
}
但如预期,这并不工作,当我调试任务只是等待在X秒存根线(api.GetSomething()之前,甚至称为)
如何调整这些测试以获得所需的行为?
作为一个额外的好处,如果可以不必等待其余的运行,这将是非常好的。
答
可以测试与“Assert.Throws”异常NUnit的assert.You可以测试出一个值后的时间x量恢复使用这样一个秒表:
[Test]
public void Api_RetrieveTakes3Seconds_SomethingReturned()
{
mockConnector.Stub(c => c.Retrieve()).Return(Task.Delay(3000).ContinueWith(c => "Something").Result);
topwatch sw = new Stopwatch();
sw.Start();
var response = api.GetSomething();
sw.Stop();
Assert.That(sw.ElapsedMilliseconds, Is.LessThanOrEqualTo(3000)); }
[Test]
public void Api_RetrieveTakes8Seconds_TimeOutExceptionThrown()
{
mockConnector.Stub(c => c.Retrieve()).Return(Task.Delay(8000).ContinueWith(c => "Something").Result);
Assert.Throws(Exception,()=> api.GetSomething());
}
您需要添加一点缓冲区,因为你的测试正在等待3秒钟,所以你应该检查测试返回的时间少于3.1秒或类似的东西。
+0
嗯,但这似乎遭受同样的问题,当在存根上调用Retrieve()时不会发生人为延迟 - 它仅在创建存根时发生。 Retrieve()调用仍然是即时的。 – FBryant87
答
对于幸福的路径,尝试
Assert.That(() => api.GetSomething(), Is.EqualTo(expected).After(3).Seconds));
您可能需要,因为它是受延迟调整时间。
失败,你需要注入模拟或假冒成API时间过长,然后...
Assert.That(() => api.GetSomething(), Throws.Typeof<MyException>());
这是所有论坛的代码,所以看的错误。 :-)
也许尝试“mockConnector.Stub(c => c.Retrieve())。Return(()=> Task.Delay(3000).ContinueWith(c =>”Something“)。Result);”让你的代码在正确的线上等待? – JBdev