Тестирование событий с фиктивными объектами NUnit
Я использую 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 ответ
Попробуйте эту статью: 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 является лишь примером того, как событие влияет на объект.