繁体   English   中英

nUnit / moq-为什么我的模拟总是返回false?

[英]nUnit / moq - why does my mock always return false?

我是使用nUnit和Moq进行单元测试的新手,在设置dbprovider中的方法的行为时遇到了问题。

我正在尝试测试在ICoDbProvider中调用Exists方法的验证方法。 如果为false,则该方法抛出异常,并且运行良好。 如果为true,则该方法应继续进行,直到return true;否则为return true; 方法末尾的语句。

这是经过测试的方法:

private bool ValidateReciboCajaModel(ReciboCajaModel model)
{
        if (model == null)
            throw new ArgumentException("El modelo ha llegado nulo");

        if (string.IsNullOrWhiteSpace(model.AccionARealizar))
            throw new ArgumentException("No se ha definido una Acción a realizar");

        if (!_accionARealizarService.Exists(new AccionARealizarEntity(model)))
            throw new ArgumentException(@"No es una ""acción a realizar"" válida");


        if (string.IsNullOrWhiteSpace(model.CentroCostos))
            throw new ArgumentException("No se ha definido ningún centro de costos");

        if (!_centroCostosService.Exists(new CentroCostosEntity(model)))
            throw new Exception("No es un centro de costos válido");

        if (String.IsNullOrWhiteSpace(model.CuentaIngresoDinero))
            throw new Exception("No es una cuenta de Ingreso válida");

        if (!_terceroService.Exists(new TerceroEntity(model)))
            throw new Exception("No es un tercero registrado");

        if (String.IsNullOrWhiteSpace(model.Tercero))
            throw new Exception("No es un tercero válido");

        if (!_tipoReciboCajaService.Exists(new TipoReciboCajaEntity(model)))
            throw new Exception("No es un recibo de caja registrado");

        if (String.IsNullOrWhiteSpace(model.TipoReciboCaja))
            throw new Exception("No es un recibo de caja válido");

        if (!(0 < model.ValorPagado && model.ValorPagado <= 999999999999d))
            throw new Exception("El valor pagado no es válido");

        return true;

}

该测试最初是由Intellitest生成的,它生成了用于私有方法测试的支架。

测试方法如下所示。

    [Test]
    [PexGeneratedBy(typeof(ReciboCajaBizTest))]
    [PexRaisedException(typeof(TargetInvocationException))]
    public void ValidateReciboCajaModel_ValidModel()
    {
        bool b;
        TargetInvocationException receivedException = new TargetInvocationException(null);

        ReciboCajaModel s1 = new ReciboCajaModel();
        var accionARealizarService = new Mock<ICoDbProvider>();
        var centroCostosService = new Mock<ICoDbProvider>();
        var terceroService = new Mock<ICoDbProvider>();
        var tipoReciboCajaService = new Mock<ICoDbProvider>();

        s1.TipoReciboCaja = "RC0";
        s1.Numero = 0;
        s1.Tercero = "tercero existente";
        s1.AccionARealizar = "some action";
        s1.FechaElaboracion = default(DateTime);
        s1.CentroCostos = "cc1";
        s1.CuentaIngresoDinero = "Débito";
        s1.ValorPagado = 1000000d;

        accionARealizarService.Setup(m => m.Exists(new AccionARealizarEntity(s1))).Returns(true);
        centroCostosService.Setup(m => m.Exists(new CentroCostosEntity(s1))).Returns(true);
        terceroService.Setup(m => m.Exists(new TerceroEntity(s1))).Returns(true);
        tipoReciboCajaService.Setup(m => m.Exists(new TipoReciboCajaEntity(s1))).Returns(true);

        ReciboCajaBiz s0 = new ReciboCajaBiz(null, accionARealizarService.Object, centroCostosService.Object,terceroService.Object,tipoReciboCajaService.Object);

        b = this.ValidateReciboCajaModel(s0, s1);

        Assert.AreEqual(true, b);
    }

在这种情况下,模型中的所有内容都是正确的,并且该方法应返回有效标志。

我在调试时有这种奇怪的行为。 设置了Mocks行为后,我立即在Watch窗口中调用了该方法,该方法返回false,如图所示

调试显示该行为未按设置进行

我也有一种方法来测试accionARealizar对象不存在,并且它返回false。 但我怀疑它是否正常工作。

更新资料

如以下评论中所要求,这是ReciboCajaModel

public class ReciboCajaModel
{
    [Required]
    [EnumDataType(enumType: typeof(TipoReciboCaja))]
    public string TipoReciboCaja { get; set; }
    [Required]
    public int Numero { get; set; }
    [Required]
    public string Tercero { get; set; }
    [Required]
    public string AccionARealizar { get; set; }
    [Required]
    public DateTime FechaElaboracion { get; set; }
    [Required]
    public string CentroCostos { get; set; }
    /// <summary>
    /// este campo no sólo enlaza la cuenta donde se hace el abono o accion a realizar, sino también la forma de pago
    /// </summary>
    [Required]
    public string CuentaIngresoDinero { get; set; }
    [Required]
    [Range(0, 999999999999)]
    public double ValorPagado { get; set; }
}

和ReciboCajaBiz构造函数和私有成员

    private ICoDbProvider _reciboCajaService;
    private ICoDbProvider _accionARealizarService;
    private ICoDbProvider _centroCostosService;
    private ICoDbProvider _terceroService;
    private ICoDbProvider _tipoReciboCajaService;

    public ReciboCajaBiz()
    {
        _reciboCajaService = new ReciboCajaService();
        _accionARealizarService = new AccionARealizarService();
    }

    public ReciboCajaBiz(ICoDbProvider reciboCajaService = null, ICoDbProvider accionARealizarService = null, ICoDbProvider centroCostosService = null, ICoDbProvider terceroService = null, ICoDbProvider tipoReciboCajaService = null)
    {
        _reciboCajaService = reciboCajaService == null ? new ReciboCajaService() : reciboCajaService;
        _accionARealizarService = accionARealizarService == null ? new AccionARealizarService() : accionARealizarService;
        _centroCostosService = centroCostosService == null ? new CentroCostosService() : centroCostosService;
        _terceroService = terceroService == null ? new TerceroService() : terceroService;
        _tipoReciboCajaService = tipoReciboCajaService == null ? new TipoReciboCajaService() : terceroService;
    }

乍一看,您的Moq表达式可能不符合您的期望。

您试图匹配Exists()函数的对象引用,这意味着它将对对象引用进行相等性检查-这将不匹配。 您正在新建两个不同的对象。

_accionARealizarService.Exists(new AccionARealizarEntity(model))

请参阅此处以了解有关Moq匹配参数的更多信息

更改模拟Setup表达式,以便更慷慨地查看这是否是问题所在。

您可以在类似表达式中使用It.IsAny()

accionARealizarService.Setup(m => m.Exists(It.IsAny<SiigoEntity>())).Returns(true);

一旦成功,您可以使用It.Is()表达式更具体地进行对象属性检查。

问题是在模拟行为集中使用对象引用。 我正在使用这个:

accionARealizarService.Setup(m => m.Exists(new AccionARealizarEntity(s1))).Returns(true);

但这将导致测试创建一个对象并将该对象与发送给Exists方法的对象进行比较,以便可以验证行为。 这将导致对Equals方法的调用,因此将始终抛出false。

为了正确地验证发送给模拟方法的参数,我应该使用以下命令:

accionARealizarService.Setup(m => m.Exists(It.IsAny<CoEntity>())).Returns(true);

It.IsAny<CoEntity>语句将指示It.IsAny<CoEntity>方法的行为,以不与对象的特定实例进行比较,而是验证对象是否为CoEntity

我得出了这个结论,并根据@Ralph答案发布了完整的答案,这使我走上了正确的道路。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM