5

我有基本运行 2 个线程的单元测试示例代码:主测试线程和我正在启动的另一个线程应该在一段时间后使测试执行失败(这基本上是一个超时线程)

代码如下:

[TestClass]
public class SomeTestClass
{
    [TestInitialize]
    public void BeforeTest()
    {
        var task = new Task(abortIfTestStilRunsAfterTimeout);
        task.Start();
    }

    [TestMethod]
    public void TestMethod()
    {
        Thread.Sleep(5000);
    }

    private void abortIfTestStilRunsAfterTimeout()
    {
        Assert.Fail("timeout passed!");

    }
}

好吧,我原以为TestMethod()测试会失败,但实际发生的是运行该Assert.Fail方法的任务线程出现异常,而另一个线程继续运行并且测试通过。

我正在寻找一种使测试方法失败的方法

4

3 回答 3

3

您可以尝试获取对测试线程的引用并调用Abort()它。您可以传递一个异常状态对象Abort(),您可以使用该对象向其传递失败消息:

[TestClass]
public class SomeTestClass
{
    Thread testThread;

    [TestInitialize]
    public void BeforeTest()
    {
        testThread = Thread.CurrentThread;
        var task = new Task(abortIfTestStilRunsAfterTimeout);
        task.Start();
    }

    [TestMethod]
    public void TestMethod()
    {
        try
        {
            Thread.Sleep(5000);
        }
        catch (ThreadAbortException e)
        {
             Assert.Fail((string)e.ExceptionState);
        }
    }

    private void abortIfTestStilRunsAfterTimeout()
    {
        testThread.Abort("timeout passed!");
    }
}

如果您不想修改大约 100 个测试,您可以使用 PostSharp 之类的工具通过try {} catch {}在每个测试用例周围插入逻辑来修改您的测试用例。归结起来就是编写一个属性并用它装饰你的测试程序集(它被称为面向方面的编程,而 PostSharp 中的框架被称为老挝)。

于 2012-04-10T09:12:37.077 回答
1

这个想法很简单 - 只需在任务/线程中运行主要测试逻辑,并将超时处理代码放入测试方法/测试初始化​​中。某种控制反转

// Test class level
ManualResetEvent mre = new ManualResetEvent(false);                                

[TestMethod]     
public void TestMethod()     
{                     
    // start waiting task
    Task task = Task.Factory.StartNew(() =>
        {
            // Test Body HERE!
            // ... 

            // if test passed - set event explicitly
            mre.Set();
        });


    // Timeout handling logic, 
    // !!! I believe you can put it once in the TestInitialize, just check
    // whether Assert.Fail() fails the test when called from TestInitialize
    mre.WaitOne(5000);

    // Check whether ManualResetEvent was set explicitly or was timeouted
    if (!mre.WaitOne(0))
    {
        task.Dispose();
        Assert.Fail("Timeout");
    }                
}                    

PS:关于WaitOne(0)技巧,MSDN

如果毫秒超时为零,则该方法不会阻塞。它测试等待句柄的状态并立即返回。

于 2012-04-10T09:09:56.633 回答
0

这篇文章有点旧,但最近我遇到了类似的问题。

我的解决方案不同:

使用 NUnit TimeoutAttribute



在此处查看 NUnit 文档:
NUnit 2.5:https
: //nunit.org/docs/2.5/timeout.html NUnit 3.0:https ://github.com/nunit/docs/wiki/Timeout-Attribute

于 2019-07-29T09:59:34.093 回答