使用 NUnit 模拟对象测试事件

本文关键字:测试 事件 对象 模拟 NUnit 使用 | 更新日期: 2023-09-27 17:55:09

我正在使用 NUnit 来测试我的应用程序,我在下面包含了它的简化版本。 我正在寻找一种方法来触发模拟类上的事件,并检查被测试的类是否已收到它。

应用程序在会话上调用 LogIn,一段时间后,会话将触发 OnLoggedIn 事件。 我已经设置了一个模拟会话,并检查了应用程序是否在其上调用登录。 现在我想在其上触发 OnLoggedIn 事件,并检查应用程序是否处理此事件。

我该怎么做?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using NUnit.Mocks;
namespace NUnitTest
{
    public delegate void LoggedInDelegate();
    public interface ISession
    {
        void LogIn(String username, String password);
        event LoggedInDelegate OnLoggedIn;
    }
    public class App
    {
        private bool loggedIn = false;
        private ISession sess;
        public bool LoggedIn
        {
            get
            {
                return loggedIn;
            }
        }
        public App(ISession sess)
        {
            this.sess = sess;
            sess.OnLoggedIn += HandleOnLoggedIn;
        }
        public void LogIn(String username, String password)
        {
            sess.LogIn(username, password);
        }
        public void HandleOnLoggedIn()
        {
            loggedIn = true;
        }
    }
    [TestFixture]
    public class AppTest
    {
        private String USERNAME = "Username";
        private String PASSWORD = "Password";
        private DynamicMock mockSess;
        private App app;
        [SetUp]
        public void TestInit()
        {
            // Create objects.
            mockSess = new DynamicMock(typeof(ISession));
            app = new App((ISession) mockSess.MockInstance);
        }
        [Test]
        public void TestLogin()
        {
            mockSess.Expect("LogIn", USERNAME, PASSWORD);
            app.LogIn(USERNAME, PASSWORD);
            mockSess.Verify();
            mockSess.Call("OnLoggedIn");
            Assert.IsTrue(app.LoggedIn);
        }
    }
}

使用 NUnit 模拟对象测试事件

试试这篇文章:https://web.archive.org/web/20110914180329/http://blog.gravityfree.ca/2007/03/raising-events-in-nmock-20.html。我真的不明白,但我会坐下来稍后尝试,因为我有同样的问题。

我通常创建一个老式的存根对象(没有模拟框架),并通过存根中的方法调用引发事件。它是这样的:

[TestFixture]
public sealed class TestStubbingEvents
{
    [Test]
    public void FooReceivesEventFromBar()
    {
        BarStub bar = new BarStub(); 
        Foo foo = new Foo(bar);
        Assert.That(foo.EventReceived, Is.False);
        bar.RaiseBarEvent();
        Assert.That(foo.EventReceived, Is.True);
    }
}
internal class Foo
{
    public bool EventReceived
    {
        get; set;
    }
    public Foo(IBar bar)
    {
        EventReceived = false;
        bar.BarEvent += ReceiveBarEvent; 
    }
    private void ReceiveBarEvent(object sender, EventArgs args)
    {
        EventReceived = true; 
    }
}
internal class BarStub : IBar
{
    public event BarEventHandler BarEvent;
    //Stub method that invokes the event
    public void RaiseBarEvent()
    {
        BarEvent.Invoke(this, new EventArgs());
    }
}

public delegate void BarEventHandler(object sender, EventArgs args);
public interface IBar
{
    event BarEventHandler BarEvent;
}

这是我想出的最好的,所以我有兴趣看看链接中的文章可以产生什么。

添加:
请注意,Foo 类上的 EventReceived 属性只是事件如何影响对象的一个示例。