我正在尝试对一个在单独线程上执行某些操作的类运行单元测试,然后使用eventhandler通知父级已完成任务。这是我的测试代码:
[TestMethod()]
public void InitTest()
{
Controller target = new Controller();
target.FinishedCommand += delegate(bool success)
{
Assert.AreEqual(true, success);
};
target.Init();
while (true)
{
}
}
这是我正在测试的方法:
public delegate void ControllerEventHandler(bool success);
public class Controller
{
public event ControllerEventHandler FinishedCommand;
public void Init()
{
FinishedCommand(true);
}
}
我意识到Init()不使用新线程,但我只是想确保测试现在正在运行。测试只是永远停留在while()循环中,而不是传递,而且永远不会输入匿名委托。
事件是否错误连接?在单元测试中可以像这样使用事件吗?
答案 0 :(得分:2)
Assert
不会停止测试,如果没有执行Assert
语句,测试也不会失败 - 因此while(true)
循环可以防止测试结束。
此外,事件的行为类似于简单的方法调用 - 因此在target.Init();
返回之前,事件已经发生。
您应该使用可以在事件处理程序中设置的变量bool eventOccurredAndSucceeded = false
,并在调用target.Init();
后进行测试:
[TestMethod()]
public void InitTest()
{
bool eventOccurredAndSucceeded = false;
Controller target = new Controller();
target.FinishedCommand += delegate(bool success)
{
if (success)
{
eventOccurredAndSucceeded = true;
}
};
target.Init();
Assert.AreEqual(true, eventOccurredAndSucceeded);
}
答案 1 :(得分:1)
可以测试事件,但我发现的最好方法是使用ManualResetEvent
。考虑这个修改:
public void InitTest()
{
Controller target = new Controller();
target.FinishedCommand += delegate(bool success)
{
Assert.AreEqual(true, success);
eventRaised.Set();
};
ManualResetEvent eventRaised = new ManualResetEvent(false);
target.Init();
eventRaised.WaitOne();
}
这里发生的是WaitOne
将停止此方法执行,等待Set()
被调用。由于Set()
在事件处理程序内部被调用,因此它会在逻辑上等待,直到事件被引发并声明为止。
但是,您必须将Assert
移到事件处理程序之外,因为该方法不会成功,因此还需要进行一些修改:
public void InitTest()
{
bool succeeded = false;
Controller target = new Controller();
target.FinishedCommand += delegate(bool success)
{
succeeded = success;
eventRaised.Set();
};
ManualResetEvent eventRaised = new ManualResetEvent(false);
target.Init();
eventRaised.WaitOne();
Assert.IsTrue(succeeded);
}