使用 FakeItEasy 断言已引发事件
Using FakeItEasy to assert that an event was raised
我可以执行以下操作来验证是否引发了我的 Consumer
class 的 ErrorOccurred
事件:
using System;
using FakeItEasy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
public interface IService
{
event EventHandler SomethingBadHappened;
}
class Consumer
{
private readonly IService service;
public Consumer(IService service)
{
this.service = service;
service.SomethingBadHappened += (sender, args) => RaiseErrorOccurred();
}
public event EventHandler ErrorOccurred;
protected virtual void RaiseErrorOccurred()
{
var handler = ErrorOccurred;
if (handler != null) handler(this, EventArgs.Empty);
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var service = A.Fake<IService>();
var consumer = new Consumer(service);
bool eventWasRaised = false;
consumer.ErrorOccurred += (sender, args) => { eventWasRaised = true; };
service.SomethingBadHappened += Raise.WithEmpty();
Assert.IsTrue(eventWasRaised);
}
}
我想知道是否有更 "Mocking Framework-y" 的方法来做到这一点。像下面这样的东西会很好:
var service = A.Fake<IService>();
var consumer = new Consumer(service);
service.SomethingBadHappened += Raise.WithEmpty();
consumer.ErrorOccurred.MustHaveHappened(/*yada yada/*);
为了让 FakeItEasy 对方法执行任何断言,该方法必须是可伪造的,并且在伪造的对象上定义。在这种情况下,consumer
是一个 "real" 对象,因此 FakeItEasy 无法知道它是否做了任何事情。
有一个替代方案,但它是否更 "Mocking Framework-y" 有待商榷。但它可能会吸引你。
创建一个假的(在本例中为 handler
)以收听 ErrorOccurred
方法:
[TestMethod]
public void TestMethod2()
{
var service = A.Fake<IService>();
var consumer = new Consumer(service);
var handler = A.Fake<EventHandler>();
consumer.ErrorOccurred += handler;
service.SomethingBadHappened += Raise.WithEmpty();
A.CallTo(()=>handler.Invoke(A<object>._, A<EventArgs>._)).MustHaveHappened();
}
这样您就可以检查 handler
是否被调用了。可以进行直接修改以确保调用是 specific number of times, or with certain arguments.
当然,如果您不关心方法被调用的次数或参数,因为 handler
上实际上只有一个方法感兴趣,您可以使用这个更简单的调用,这将匹配 any 对处理程序的调用(可能 Invoke
):
A.CallTo(handler).MustHaveHappened();
我可以执行以下操作来验证是否引发了我的 Consumer
class 的 ErrorOccurred
事件:
using System;
using FakeItEasy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
public interface IService
{
event EventHandler SomethingBadHappened;
}
class Consumer
{
private readonly IService service;
public Consumer(IService service)
{
this.service = service;
service.SomethingBadHappened += (sender, args) => RaiseErrorOccurred();
}
public event EventHandler ErrorOccurred;
protected virtual void RaiseErrorOccurred()
{
var handler = ErrorOccurred;
if (handler != null) handler(this, EventArgs.Empty);
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var service = A.Fake<IService>();
var consumer = new Consumer(service);
bool eventWasRaised = false;
consumer.ErrorOccurred += (sender, args) => { eventWasRaised = true; };
service.SomethingBadHappened += Raise.WithEmpty();
Assert.IsTrue(eventWasRaised);
}
}
我想知道是否有更 "Mocking Framework-y" 的方法来做到这一点。像下面这样的东西会很好:
var service = A.Fake<IService>();
var consumer = new Consumer(service);
service.SomethingBadHappened += Raise.WithEmpty();
consumer.ErrorOccurred.MustHaveHappened(/*yada yada/*);
为了让 FakeItEasy 对方法执行任何断言,该方法必须是可伪造的,并且在伪造的对象上定义。在这种情况下,consumer
是一个 "real" 对象,因此 FakeItEasy 无法知道它是否做了任何事情。
有一个替代方案,但它是否更 "Mocking Framework-y" 有待商榷。但它可能会吸引你。
创建一个假的(在本例中为 handler
)以收听 ErrorOccurred
方法:
[TestMethod]
public void TestMethod2()
{
var service = A.Fake<IService>();
var consumer = new Consumer(service);
var handler = A.Fake<EventHandler>();
consumer.ErrorOccurred += handler;
service.SomethingBadHappened += Raise.WithEmpty();
A.CallTo(()=>handler.Invoke(A<object>._, A<EventArgs>._)).MustHaveHappened();
}
这样您就可以检查 handler
是否被调用了。可以进行直接修改以确保调用是 specific number of times, or with certain arguments.
当然,如果您不关心方法被调用的次数或参数,因为 handler
上实际上只有一个方法感兴趣,您可以使用这个更简单的调用,这将匹配 any 对处理程序的调用(可能 Invoke
):
A.CallTo(handler).MustHaveHappened();