Допустимо ли делать утверждения в ваших обратных вызовах, если вы позже убедитесь, что методы были вызваны? Является ли это предпочтительным способом убедиться, что мой макет получает ожидаемые параметры, переданные ему, или я должен установить локальную переменную в своем обратном вызове и выполнить утверждения в этом экземпляре?
У меня есть ситуация, когда у меня есть некоторая логика в классе 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);
}