Подписка на мероприятие RhinoMocks

Будучи новичком в RhinoMocks и модульном тестировании, я столкнулся с проблемой, решение которой я не могу найти (независимо от того, сколько документации я читал).

Проблема в следующем: я создал интерфейс, который предоставляет 5 событий (для использования в представлении в ASP.NET и шаблоне надзорного контроллера MVP ... Я знаю, я должен использовать MVC, но это совсем другое проблема). В любом случае, я хочу проверить, что, когда в представлении срабатывает определенное событие, мы назовем его «IsLoaded», что вызывается метод внутри моего Presenter и, используя внедрение зависимостей, значение возвращается из зависимости и устанавливается на вид. Вот где начинается проблема: когда я использую Expect.Call (Dependency.GetInfo ()). Return (SomeList), Call никогда не выполняется (без вызова метода mock.ReplayAll ()). Что ж, когда я вызываю метод ReplayAll, я получаю ExpectationExceptions из-за подписки объекта Presenter на другие события, предоставляемые интерфейсом просмотра.

Итак, чтобы я мог проверить, что IView.IsLoaded сработал, я хочу убедиться, что IView.ListOfSomething был обновлен в соответствии со списком, который я передал через Expect.Call (). Однако, когда я устанавливаю ожидание, другие подписки на события (которые происходят прямо из конструктора для Presenter) не соответствуют ожиданиям # 0 теста. Я получаю следующее: view.Save + = this.SaveNewList подбрасывает исключение RhinoMocks ExpectationViolationException.

Мой вопрос на миллион долларов таков: нужно ли мне устанавливать ожидания для ВСЕХ моих событий (через [Setup]), или я что-то упускаю / не понимаю в том, как работает Unit Testing или RhinoMocks?

Имейте в виду, что я чрезвычайно новичок в модульном тестировании и, следовательно, в RhinoMocks. Если окажется, что я не понимаю, о чем говорю, не стесняйтесь указать на это.


person jstephenson    schedule 26.11.2008    source источник
comment
Просто обновление, так как оно может помочь кому-то еще, у кого есть такая же проблема: я обнаружил свой фатальный недостаток. В своих новичках я создавал макет представления не с помощью mock.DynamicMock ‹›, а с помощью .CreateMock ‹›. Я такой глупый. Эти вызовы методов, отличных от определенных, вызвали исключение.   -  person jstephenson    schedule 26.11.2008


Ответы (1)


Я работаю над проектом, в котором мы также использовали MVP и моки rhino. Мы просто ожидали всех подписок на события в каждом тесте.

    private void SetupDefaultExpectations()
    {
        _mockView.Initializing += null; LastCall.IgnoreArguments();
        _mockView.SavingChanges += null; LastCall.IgnoreArguments();
    }

Затем мы создали метод расширения для IMockedObject (от RhinoMocks) для запуска событий в модульных тестах и ​​исключения исключений, чтобы их можно было ожидать стандартным способом NUnit.

static class IMockedObjectExtension
{
    public static void RaiseEvent(this IMockedObject mockView, string eventName, EventArgs args)
    {
        EventRaiser eventraiser = new EventRaiser(mockView, eventName);

        try
        {
            eventraiser.Raise(mockView, args);
        }
        catch (TargetInvocationException ex)
        {
            throw ex.InnerException;
        }
    }

    public static void RaiseEvent(this IMockedObject mockView, string eventName)
    {
        RaiseEvent(mockView, eventName, EventArgs.Empty);
    }
}

Затем это можно было бы использовать из модульного теста следующим образом

using(_mocks.Record())
{
    Expect.Call(dependency.GetInfo()).Return(someList);
}
using(_mocks.Playback())
{
    Presenter presenter = new Presenter(_mockView, dependency);
    (_mockView as IMockedObject).RaiseEvent("SavingChanges");
}

Чтобы исключить дублирование между тестами презентатора, мы преобразовали его в базовый класс BasePresenterTest, который устанавливает эту базовую структуру для всех тестов презентатора и предоставляет вспомогательные методы подклассу.

public abstract class BasePresenterTest<VIEW> where VIEW : IBaseView
{
    protected MockRepository _mocks;
    protected VIEW View { get; private set; }

    protected abstract void SetUp();
    protected abstract void TearDown();
    protected abstract void SetupDefaultExpectations();

    [SetUp]
    public virtual void BaseSetUp()
    {
        _mocks = new MockRepository();
        View = _mocks.CreateMock<VIEW>();

        SetUp();
    }

    [TearDown]
    public virtual void BaseTearDown()
    {
        TearDown();

        View = null;
        _mocks = null;
    }

    protected virtual void BaseSetupDefaultExpectations()
    {
        //Setup default expectations that are general for all views
        SetupDefaultExpectations();
    }

    protected virtual IDisposable Record()
    {
        IDisposable mocksRecordState = _mocks.Record();

        BaseSetupDefaultExpectations();

        return mocksRecordState;
    }

    protected virtual IDisposable Playback()
    {
        return _mocks.Playback();
    }

    protected void RaiseEventOnView(string eventName)
    {
        (View as IMockedObject).RaiseEvent(eventName);
    }       
}

Это избавляет от большого количества кода из тестов в нашем проекте.

Мы по-прежнему используем старую версию RhinoMocks, но я постараюсь обновить ее, когда мы перейдем к более поздней версии.

person maz    schedule 03.12.2008