C# - 测试在X秒后断言组件超时

时间:2017-05-10 16:08:02

标签: c# nunit rhino-mocks

假设我有一个像这样的简单Api类,在那里进行外部调用但是如果它没有完成则在5秒后抛出异常:

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()之前)时,这并没有按预期工作

如何调整这些测试以获得所需的行为?

作为一个额外的奖励,如果有可能不必等待休息时间,那就太棒了。

2 个答案:

答案 0 :(得分:0)

您可以使用“Assert.Throws”nunit断言测试异常。您可以使用秒表测试在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秒或类似的情况。

答案 1 :(得分:0)

对于快乐的道路,请尝试

Assert.That(() => api.GetSomething(), Is.EqualTo(expected).After(3).Seconds));

您可能需要调整时间,因为它会受到延迟的影响。

对于失败,你需要在api中注入模拟或假冒,这需要太长时间然后......

Assert.That(() => api.GetSomething(), Throws.Typeof<MyException>());

这是所有论坛代码,因此请注意错误。 : - )