用nunit测试事件

ata*_*man 36 c# events nunit unit-testing c#-2.0

我刚刚开始使用TDD,可以解决我自己遇到的大部分问题.但现在我迷路了:如何检查事件是否被解雇?我在寻找类似的东西Assert.Raise,Assert.Fire但什么都没有.谷歌不是很有用,大多数的点击是类似的建议,foo.myEvent += new EventHandler(bar); Assert.NotNull(foo.myEvent);但没有任何证据.

谢谢!

Dro*_*per 47

检查事件是否被触发可以通过订阅该事件并设置布尔值来完成:

var wasCalled = false;
foo.NyEvent += (o,e) => wasCalled = true;

...

Assert.IsTrue(wasCalled);
Run Code Online (Sandbox Code Playgroud)

由于要求 - 没有lambdas:

var wasCalled = false;
foo.NyEvent += delegate(o,e){ wasCalled = true;}

...

Assert.IsTrue(wasCalled);
Run Code Online (Sandbox Code Playgroud)


ade*_*esh 15

我更喜欢这样做:

var wait = new AutoResetEvent(false);
foo.MeEvent += (sender, eventArgs) => { wait.Set(); };
Assert.IsTrue(wait.WaitOne(TimeSpan.FromSeconds(5)));
Run Code Online (Sandbox Code Playgroud)

优点:支持多线程场景(如果在不同的线程中调用处理程序)

  • 我正在采用类似的方法,但更喜欢`ManualResetEvent`。 (2认同)

Cla*_*lay 10

如果您知道该事件将同步触发:

bool eventRaised = false;
Customer customer = new Customer() { Name = "Carl" };
customer.NameChanged += (sender, e) => { eventRaised = true; };

customer.Name = "Sam";

Assert.IsTrue(eventRaised);
Run Code Online (Sandbox Code Playgroud)

如果事件可能异步触发:

ManualResetEvent eventRaised = new ManualResetEvent(false);
Customer customer = new Customer() { Name = "Carl" };
customer.NameChanged += (sender, e) => { eventRaised.Set(); };

customer.Name = "Sam";

Assert.IsTrue(eventRaised.WaitOne(TIMEOUT));
Run Code Online (Sandbox Code Playgroud)

但是,有人说应该避免测试异步行为.


ear*_*ess 5

我最近不得不这样做,下面是我提出的.我没有做其他帖子所说的原因是我不喜欢变量保持状态的想法,并且不得不在多个事件之间"手动"重置它.

下面是在测试中测试的ClassUnderTestwith NameChanged事件的代码MyTests:

public class ClassUnderTest {
    private string name;
    public string Name {
        get { return this.name; }
        set {
            if (value != this.name) {
                this.name = value;
                NameChanged(this, new PropertyChangedEventArgs("Name"));
            }
        }
    }

    public event EventHandler<PropertyChangedEventArgs> NameChanged = delegate { };
}

[TestFixture]
public class MyTests {
    [Test]
    public void Test_SameValue() {
        var t = new ClassUnderTest();
        var e = new EventHandlerCapture<PropertyChangedEventArgs>();
        t.NameChanged += e.Handler;

        Event.Assert(e, Event.IsNotRaised<PropertyChangedEventArgs>(), () => t.Name = null);
        t.Name = "test";
        Event.Assert(e, Event.IsNotRaised<PropertyChangedEventArgs>(), () => t.Name = "test");
    }
    [Test]
    public void Test_DifferentValue() {
        var t = new ClassUnderTest();
        var e = new EventHandlerCapture<PropertyChangedEventArgs>();
        t.NameChanged += e.Handler;

        Event.Assert(e, Event.IsPropertyChanged(t, "Name"), () => t.Name = "test");
        Event.Assert(e, Event.IsPropertyChanged(t, "Name"), () => t.Name = null);
    }
}
Run Code Online (Sandbox Code Playgroud)

支持课程如下.这些类可以与任何EventHandler<TEventArgs>或扩展到其他代表一起使用.事件测试可以嵌套.

/// <summary>Class to capture events</summary>
public class EventHandlerCapture<TEventArgs> where TEventArgs : EventArgs {
    public EventHandlerCapture() {
        this.Reset();
    }

    public object Sender { get; private set; }
    public TEventArgs EventArgs { get; private set; }
    public bool WasRaised { get; private set; }

    public void Reset() {
        this.Sender = null;
        this.EventArgs = null;
        this.WasRaised = false;
    }

    public void Handler(object sender, TEventArgs e) {
        this.WasRaised = true;
        this.Sender = sender;
        this.EventArgs = e;
    }
}

/// <summary>Contains things that make tests simple</summary>
public static class Event {
    public static void Assert<TEventArgs>(EventHandlerCapture<TEventArgs> capture, Action<EventHandlerCapture<TEventArgs>> test, Action code) where TEventArgs : EventArgs {
        capture.Reset();
        code();
        test(capture);
    }
    public static Action<EventHandlerCapture<TEventArgs>> IsNotRaised<TEventArgs>() where TEventArgs : EventArgs {
        return (EventHandlerCapture<TEventArgs> test) => {
            NUnit.Framework.Assert.That(test.WasRaised, Is.False);
        };
    }
    public static Action<EventHandlerCapture<PropertyChangedEventArgs>> IsPropertyChanged(object sender, string name) {
        return (EventHandlerCapture<PropertyChangedEventArgs> test) => {
            NUnit.Framework.Assert.That(test.WasRaised, Is.True);
            NUnit.Framework.Assert.That(test.Sender, Is.SameAs(sender));
            NUnit.Framework.Assert.That(test.EventArgs.PropertyName, Is.EqualTo(name));
        };
    }
}
Run Code Online (Sandbox Code Playgroud)