如何测试引发事件是否会导致根据参数值调用方法
我正在尝试编写一个单元测试,它将在我的测试类绑定到的模拟对象上引发一个事件。
但我热衷于测试的是,当我的测试类调用其事件处理程序时,它应该只对事件处理程序参数的某些值调用方法。
即使我评论调用 ProcessPriceUpdate(price); 的代码,我的测试似乎还是通过了。
我在 VS2005 中,所以请不要使用 lambda :(
所以...
public delegate void PriceUpdateEventHandler(decimal price);
public interface IPriceInterface{
event PriceUpdateEventHandler PriceUpdate;
}
public class TestClass
{
IPriceInterface priceInterface = null;
TestClass(IPriceInterface priceInterface)
{
this.priceInterface = priceInterface;
}
public void Init()
{
priceInterface.PriceUpdate += OnPriceUpdate;
}
public void OnPriceUpdate(decimal price)
{
if(price > 0)
ProcessPriceUpdate(price);
}
public void ProcessPriceUpdate(decimal price)
{
//do something with price
}
}
到目前为止我的测试...:s
public void PriceUpdateEvent()
{
MockRepository mock = new MockRepository();
IPriceInterface pi = mock.DynamicMock<IPriceInterface>();
TestClass test = new TestClass(pi);
decimal prc = 1M;
IEventRaiser raiser;
using (mock.Record())
{
pi.PriceUpdate += null;
raiser = LastCall.IgnoreArguments().GetEventRaiser();
Expect.Call(delegate { test.ProcessPriceUpdate(prc); }).Repeat.Once();
}
using (mock.Playback())
{
test.Init();
raiser.Raise(prc);
}
}
I'm trying to write a unit test that will raise an event on a mock object which my test class is bound to.
What I'm keen to test though is that when my test class gets its eventhandler called, it should only call a method on certain values of the eventhandler's parameters.
My test seems to pass even if I comment the code that calls ProcessPriceUpdate(price);
I'm in VS2005 so no lambdas please :(
So...
public delegate void PriceUpdateEventHandler(decimal price);
public interface IPriceInterface{
event PriceUpdateEventHandler PriceUpdate;
}
public class TestClass
{
IPriceInterface priceInterface = null;
TestClass(IPriceInterface priceInterface)
{
this.priceInterface = priceInterface;
}
public void Init()
{
priceInterface.PriceUpdate += OnPriceUpdate;
}
public void OnPriceUpdate(decimal price)
{
if(price > 0)
ProcessPriceUpdate(price);
}
public void ProcessPriceUpdate(decimal price)
{
//do something with price
}
}
And my test so far... :s
public void PriceUpdateEvent()
{
MockRepository mock = new MockRepository();
IPriceInterface pi = mock.DynamicMock<IPriceInterface>();
TestClass test = new TestClass(pi);
decimal prc = 1M;
IEventRaiser raiser;
using (mock.Record())
{
pi.PriceUpdate += null;
raiser = LastCall.IgnoreArguments().GetEventRaiser();
Expect.Call(delegate { test.ProcessPriceUpdate(prc); }).Repeat.Once();
}
using (mock.Playback())
{
test.Init();
raiser.Raise(prc);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我通常会把这种事情分成至少两个测试。第一个验证触发事件是否调用适当的回调(并且该回调始终被调用,没有条件)。您尝试测试的条件逻辑将进入适当的回调,并通过其他单独的测试进行测试。
第一个测试可以通过从被测类创建派生类来实现,并覆盖适当的回调以简单地记录它被成功调用。然后,当您触发事件时,您可以验证回调是否被调用。
下一步是直接测试回调方法,就像测试任何其他方法一样。
这是一个框架测试,其中包含第一次测试所需的验证代码。请注意,OnPriceUpdate 将在 TestClass 中虚拟化:
您以后的测试可以直接测试 OnPriceUpdate。
I will usually break this kind of thing into at least two tests. The first verifies that triggering the event calls the appropriate callback (and that callback is ALWAYS called, no conditions). The conditional logic you were trying to test, that goes into the appropriate callback, which is tested by additional separate tests.
The first test can be implemented by creating a derived class from the class under test, with the appropriate callback overriden to simply record that it was called successfully. Then when you trigger the event, you can verify the callback is called.
Next step is to test the callback method directly, as you would any other method.
Here's a skeleton test with the validation code you'd need for the first test. Note that OnPriceUpdate would be made virtual in TestClass:
Your later tests can test OnPriceUpdate directly.