¿Es aceptable hacer afirmaciones en sus devoluciones de llamada si luego verifica que se invocaron los métodos? ¿Es esta la forma preferida de asegurarme de que mi simulación obtenga los parámetros esperados, o debo establecer una variable local en mi devolución de llamada y hacer las afirmaciones en esa instancia?La forma correcta de verificar los parámetros que se pasan a un simulacro se establece como se esperaba
Tengo una situación en la que tengo cierta lógica en una clase Presenter que deriva valores basados en entradas y los pasa a una clase Creator. Para probar la lógica en la clase Presenter, quiero verificar que se observen los valores derivados adecuados cuando se llame al Creador. Se me ocurrió el siguiente ejemplo que funciona, pero no estoy seguro de si me gusta este enfoque:
[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());
}
}
que a mí respecta, ya que sin la llamada Verify
al final, no hay garantía de que la aserción en la devolución de llamada sería invocada. Otro enfoque sería establecer una variable local en la devolución de llamada:
[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);
}
siento que este enfoque es menos propenso a errores, ya que es más explícito, y es fácil ver que las declaraciones Assert
serán llamados. ¿Un enfoque es preferible al otro? ¿Hay alguna manera más sencilla de probar el parámetro de entrada pasado a un simulacro que me falta?
En caso de que sea útil, aquí está el resto del código para este ejemplo:
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);
}
EDITAR
He actualizado el código para hacer que el segundo enfoque esbocé en la pregunta más fácil de usar . Saqué la creación de la expresión utilizada en Configuración/Verificar en una variable separada, así que solo tengo que definirla una vez. Siento que este método es lo que más me gusta, es fácil de configurar y falla con buenos mensajes de error.
[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);
}
Estoy de acuerdo en que el segundo enfoque es preferible. Me gusta la sugerencia de @aqwert de usar Verify, pero los mensajes de error son demasiado difíciles de usar. Agregué un código a la pregunta original que actualiza el segundo enfoque, por lo que solo debo declarar la expresión una vez. Creo que me quedaré con ese enfoque. – rsbarro