在Visual Studio 2008中使用断点单元测试多线程环境

时间:2011-02-18 10:31:31

标签: c# multithreading visual-studio-2008 unit-testing

我在Visual Studio 2008中调试单元测试时遇到问题。单元测试使用System.Timers.Timer(在业务逻辑中)来处理某个延迟(1'000毫秒)。运行测试的线程将进入休眠状态5,000小时。

当自己运行测试时,它会通过。当运行所有测试(> 120)时,它有时会通过,有时会失败(不确定)。然后我尝试在模拟对象中设置断点,在那里我设置在单元测试中断言的标志。现在,当我自己调试测试时,我得到了Assert.IsTrue()失败的现象,但Quick Watch告诉我,这是真的:

Assert.IsTrue(true) fails: why?

public class ObjectManagerAccessMock : IObjectManagerAccess
{
    public bool ExecuteCommandWasCalled { get; set; }

    public void ExecuteCommand()
    {
        ExecuteCommandWasCalled = true; //set breakpoint here
    }
}

当另一个线程停止时(通过断点),运行测试的线程是否继续运行?

2 个答案:

答案 0 :(得分:1)

我怀疑你在调试时看到的是副作用。断言失败,因为它是错误的,但由于线程问题,当您在调试器中查看它时,该值为true。

增加测试中的超时应解决问题,但要小心。

一开始计时器似乎是一个好主意,但它们可能会在以后导致问题。环境问题,例如其他执行进程或在较慢的机器上运行测试,将推动计时器的使用方式。不幸的是,如果你将超时增加到满足最慢机器的需要,你最终会得到一系列非常慢的测试。

不要在测试中使用Thread.Sleep,而应考虑寻找使测试运行速度与代码一样快的方法。例如,在操作完成后,在测试主题上引发事件。

[Test]
public void DemonstrateThatTheTestRunsAsFastAsTheSubjectUnderTest()
{
     var resetEvent = new ManualResetEvent(true);

     // configure our test to listen for the completed event
     var subject = new MyTestSubject();
     subject.OnComplete += (sender,e) => resetEvent.Set();

     // perform the long running asynchronous operation
     subject.DoLongRunningOperation();

     // wait up to 10 seconds
     resetEvent.WaitOne(100000);

     Assert.AreTrue(subject.OperationComplete);
}

在上面,我们使用 ManualResetEvent ,它将阻止执行,直到调用 Set 操作。另请注意,我正在为重置事件提供超时值,以便操作不会永远运行。如果超时超时,我们的 OperationComplete 可能仍为false,因此测试失败。

如果您想要更精细的细节来确定测试是否超时, WaitOne 方法会返回一个布尔值,指示操作是否成功。

bool completedWithoutTimeout = resetEvent.WaitOne(10000);
Assert.IsTrue(completedWithoutTimeout, "The operation timed out.");

答案 1 :(得分:0)

有时候你的BL占用时间超过4秒,因此加起来超过5秒并且断言失败,但是当你能够通过Quick Watch操作检查它时,操作完成并且调用将值设置为true。 / p>

我非常肯定1)断言失败原因值在断言时为假2)当你检查时值为真,并且这两个动作之间的时间> 0