C#Moq框架返回null引用不正确的对象

时间:2018-01-12 15:47:45

标签: c# unit-testing mocking moq

我在单元测试中遇到问题,我使用moq框架来模拟我的数据库接口以返回数据集。问题是,当我调用BLL方法时,它返回null而不是我设置的对象。 BLL代码是:

public ApplicationsManager(IApplicationsManagerDal applicationsManagerDal)
{
    _applicationsManagerDal = applicationsManagerDal ?? throw new Exception("applicationsManagerDAL is null");
}

public IpApplication AddIpApplication(IpApplication ipApplication)
{

    try
    {
        if (Validator.ExecuteValidation(ipApplication, new AddIpApplicationValidationRules()).ValidationFailures != null)
            return ipApplication;

        ipApplication = _applicationsManagerDal.AddIpApplication(ipApplication);

        ipApplication.Status = CommonStatus.OperationOk;
        }
        catch (BaseException e)
        {
            ipApplication.Status = e.Status;
        }
        catch (Exception e)
        {
            ipApplication.Status = ExceptionHandler.SetStatusForException();

            NLogger.LogException("IpApplication Name:" + ipApplication.Name, e);
        }

        return ipApplication;
    }

我设置moq的代码是:

var _mock = new Mock<IApplicationsManagerDal>();

_mock.Setup(a => a.AddIpApplication(new IpApplication
{
   Code = new Guid("00000000-B935-4E12-9037-000000000000"),
   Name = "APPLICATION_ZERO"
}))
.Returns(() => new IpApplication
{
    Code = new Guid("9631E691-B935-4E12-9037-2E874DB15B0D"),
    Description = "Test application",
    Enabled = true,
    Name = "APPLICATION_ZERO",
});

,单元测试是:

[TestMethod(), TestCategory("Unit")]
public void AddIpApplication_ValidRequest_IpApplicationSuccessfullyAdded()
{
    // Arrange
    _ipApplication = new IpApplication
        {
            Code = new Guid("9631E691-B935-4E12-9037-2E874DB15B0D"),
            Name = "APPLICATION_ZERO"
        };

    // Act AddIpApplication
    _ipApplication = _applicationManager.AddIpApplication(_ipApplication);

    Assert.IsTrue(_ipApplication.Code != Guid.Empty);
}

当测试调用时,BLL方法到达了行:

ipApplication = _applicationsManagerDal.AddIpApplication(ipApplication);

它总是返回null。 你能解释一下为什么吗?我如何获得设定值或如何更改单元测试? 谢谢你,抱歉我的英文不好

2 个答案:

答案 0 :(得分:1)

如果没有像设置的那样完全调用模拟,它将不会按预期运行。

在您的情况下,您将传递与模拟不同的实例/引用,而不是模拟设置中使用的实例/引用。这将导致mock在调用时返回null(默认行为)。

为了获得更多关于传递参数的灵活性,您可以使用It.IsAny<IpApplication>()接受任何参数以及Callback来设置所提供参数的所需属性。这应该允许使用提供的模拟来执行测试中的方法。

_mock
    .Setup(_ => _.AddIpApplication(It.IsAny<IpApplication>()))
    .Callback((IpApplication arg) => { //<-- use call back to modify the provided parameter
        arg.Code = new Guid("9631E691-B935-4E12-9037-2E874DB15B0D");
        arg.Description = "Test application";
        arg.Enabled = true;
        arg.Name = "APPLICATION_ZERO";
    })
    .Returns((IpApplication arg) => arg); //<-- return provided parameter after Callback

//inject the mock into the subject under test.
_applicationManager = new ApplicationsManager(mock.Object);

参考Moq Quickstart以获取有关如何使用框架的更多详细信息。

答案 1 :(得分:0)

问题是您在安装程序中使用的IpApplication实例引用了与您在执行期间传入的对象不同的对象,因此设置条件不匹配。

_mock.Setup(a => a.AddIpApplication(new IpApplication
{
   Code = new Guid("00000000-B935-4E12-9037-000000000000"),
   Name = "APPLICATION_ZERO"
}))

您可以覆盖特定类的相等方法,也可以更改安装程序中的逻辑,例如:

_mock.Setup(a => a.AddIpApplication(It.Is<IpApplication>(i => i.Code == expectedGuid && i.Name = expectedString))

如果您不关心确切的值,请使用It.IsAny<IpApplication>()