Правильный способ проверить, что параметры, передаваемые в Mock, установлены должным образом

Допустимо ли делать утверждения в ваших обратных вызовах, если вы позже убедитесь, что методы были вызваны? Является ли это предпочтительным способом убедиться, что мой макет получает ожидаемые параметры, переданные ему, или я должен установить локальную переменную в моем обратном вызове и выполнить утверждения в этом экземпляре?

У меня есть ситуация, когда у меня есть некоторая логика в класс Presenter, который получает значения на основе входных данных и передает их классу Creator. Чтобы проверить логику в классе Presenter, я хочу убедиться, что при вызове Creator соблюдаются правильные производные значения. Я пришел к приведенному ниже примеру, который работает, но я не уверен, нравится ли мне этот подход:

[TestFixture]
public class WidgetCreatorPresenterTester
{
    [Test]
    public void Properly_Generates_DerivedName()
    {
        var widgetCreator = new Mock<IWidgetCreator>();
        widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
                     .Callback((Widget widget) => 
                     Assert.AreEqual("Derived.Name", widget.DerivedName));

        var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
        presenter.Save("Name");

        widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
    }
}

Я обеспокоен, потому что без вызова Verify в конце нет гарантии, что assert в обратном вызове будет вызываться. Другой подход - установить локальную переменную в обратном вызове:

[Test]
public void Properly_Generates_DerivedName()
{
    var widgetCreator = new Mock<IWidgetCreator>();
    Widget localWidget = null;
    widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
        .Callback((Widget widget) => localWidget = widget);

    var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
    presenter.Save("Name");

    widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
    Assert.IsNotNull(localWidget);
    Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}

Я считаю, что этот подход менее подвержен ошибкам, поскольку он более явный, и легче увидеть, что будут вызваны операторы Assert . Один подход предпочтительнее другого? Есть ли более простой способ проверить входной параметр, переданный в макет, который мне не хватает?

Если это полезно, вот остальная часть кода для этого примера:

public class Widget
{
    public string Name { get; set; }
    public string DerivedName { get; set; }
}

public class WidgetCreatorPresenter
{
    private readonly IWidgetCreator _creator;

    public WidgetCreatorPresenter(IWidgetCreator creator)
    {
        _creator = creator;
    }

    public void Save(string name)
    {
        _creator.Create(
            new Widget { Name = name, DerivedName = GetDerivedName(name) });
    }

    //This is the method I want to test
    private static string GetDerivedName(string name)
    {
        return string.Format("Derived.{0}", name);
    }
}

public interface IWidgetCreator
{
    void Create(Widget widget);
}

РЕДАКТИРОВАТЬ
Я обновил код, чтобы упростить использование второго подхода, который я изложил в вопросе. Я выделил создание выражения, используемого в Setup / Verify, в отдельную переменную, поэтому мне нужно определить его только один раз. Мне кажется, что этот метод - то, что мне удобнее всего, его легко настроить и он не работает с хорошими сообщениями об ошибках.

[Test]
public void Properly_Generates_DerivedName()
{
    var widgetCreator = new Mock<IWidgetCreator>();
    Widget localWidget = null;

    Expression<Action<IWidgetCreator>> expressionCreate = 
        (w => w.Create(It.IsAny<Widget>()));
    widgetCreator.Setup(expressionCreate)
        .Callback((Widget widget) => localWidget = widget);

    var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
    presenter.Save("Name");

    widgetCreator.Verify(expressionCreate, Times.Once());
    Assert.IsNotNull(localWidget);
    Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
6
задан rsbarro 23 April 2011 в 04:36
поделиться