Тестирование событий с фиктивными объектами NUnit - PullRequest
0 голосов
/ 07 мая 2011

Я использую NUnit для тестирования своего приложения, которое я включил в упрощенную версию ниже. Я ищу способ вызвать событие в фиктивном классе и убедиться, что тестируемый класс получил его.

Приложение вызывает LogIn для сеанса, и спустя некоторое время сеанс запускает событие OnLoggedIn. Я установил фиктивную сессию и проверил, что приложение вызывает в ней LogIn. Теперь я хочу запустить событие 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);
        }
    }
}

1 Ответ

1 голос
/ 10 мая 2011

Попробуйте эту статью: 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;
}

Это лучшее, что я придумал, поэтому мне интересно посмотреть, что может дать статья в ссылке.

Добавлено:
Обратите внимание, что свойство EventReceived класса Foo является лишь примером того, как событие влияет на объект.

...