MOQ单元测试 - 返回类型

时间:2015-10-12 13:43:33

标签: c# unit-testing moq

我对MOQ很新,有一个我无法解决的问题。我正在测试以下代码(我正在测试第一个 - ValidateInputBankFile ):

    #region Constructor

    private readonly IErrorRepository _errorRepository;
    private readonly IFileSystem _fileSystem;
    public IP_BankInfoDeserializer(IErrorRepository errorRepository, IFileSystem fileSystem)
    {
        _errorRepository = errorRepository;
        _fileSystem = fileSystem;
    }
    #endregion

    public IP_BankInfo ValidateInputBankFile(string sPath, App.BankType bankType)
    {
        if (!_fileSystem.FileExists((sPath)))
            return null;

        //first retrieve representative bank info
        var tmpInfo = DeserializeBankInfo(bankType);

        if (tmpInfo == null)
            return null;//Does not exist

        return tmpInfo;
    }

    public IP_BankInfo DeserializeBankInfo(App.BankType bankType)
    {
        if (!IsFileCorrect(bankType))
            return null;

        IP_BankInfo info = new IP_BankInfo();

        using (var stream = new StreamReader(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + sFolder + Path.DirectorySeparatorChar +
                                              bankType.ToString() + ".xml"))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(IP_BankInfo));
            try
            {
                info = serializer.Deserialize(stream) as IP_BankInfo;
            }
            catch (Exception ex)
            {
                info = null;
            }
        }

        return info;
    }

这是我的测试方法:

    [TestMethod]
    public void ValidateInputBank_ExistingPath_ExistingBank()
    {
        Mock<IFileSystem> fileSystem = new Mock<IFileSystem>();
        fileSystem.Setup(n => n.FileExists(null)).Returns(true);

        Mock<IP_BankInfoDeserializer> mocSerializer = new Mock<IP_BankInfoDeserializer>();
        mocSerializer.Setup(n => n.DeserializeBankInfo(App.BankType.UniCredit)).Returns(new Models.IP_BankInfo());

        var result = mocSerializer.Object.ValidateInputBankFile(null, App.BankType.UniCredit);

        //Assert.AreEqual(serializer.Object.ValidateInputBankFile(null, App.BankType.UniCredit), new Models.IP_BankInfo());
    }

我想要做的是避免调用 DeserializeBankInfo ,返回新的IP_BankInfo,以便我可以在最后的断言阶段检查它。

问题是我的 var result 总是返回null。我不明白我做错了什么?

它也失败了以下代码mocSerializer.Setup(n => n.DeserializeBankInfo(App.BankType.UniCredit)).Returns(()=>null);,但我传递了正确的参数。

2 个答案:

答案 0 :(得分:2)

回答您的问题

  

问题是我的var结果总是返回null。我不明白我做错了什么?

ValidateInputBankFile永远不会设置,你使用松散的模拟,因此它将返回null。

通过在模拟的构造函数中传递MockBehavior.Strict来使用严格模拟,并且会有一个异常,告诉您方法未设置。

应用一个安装程序,为ValidateInputBankFile方法在该模拟上返回一个合适的值,它将表现正常。

提供建议

您正在测试中调用模拟对象上的方法:

var result = mocSerializer.Object.ValidateInputBankFile(null, App.BankType.UniCredit);

根据经验,您不应该在xxx.Object.MyMethod()

上调用方法

你不应该这样做的原因是因为你基本上只是把你的“安排”部分称为测试。

我觉得我需要问你这是通过这样做来实现的,因为你基本上只是测试你的测试

答案 1 :(得分:0)

就我而言,看起来你正在尝试测试你的课程,但同时也要模拟它,以便不是所有课程都运行。 认为这是不正确的,有效地您如何知道反序列化代码是否正常工作?

如果你的答案是另一个你在课堂上模拟其他功能的测试,我会回复说你需要将BankInfo的反序列化功能抽象到另一个你可以模拟并将其注入的接口/类中你的IBankInfoValidator

这意味着您要从对象的反序列化中分离出验证,如果您的用例发生变化,这将有助于将来测试和可维护性/可扩展性。

就我个人而言,我刚刚废弃你的测试,开始寻找抽象出对象的反序列化,然后考虑将它作为单独的类进行测试。