如何在被测试的同一个类中模拟一个方法?

时间:2018-06-01 14:35:06

标签: c# unit-testing moq

我正在为服务ValidateObject中的方法ObjectService创建一些单元测试。 ValidateObject方法调用另一种方法ValidateObjectPropertyB。我想模拟对最后一个方法的调用。

ObjectService和相关方法如下所示:

public class ObjectService : IObjectService
{
    public bool ValidateObject(object objectToValidate)
    {
        return 
            !String.IsNullOrEmpty(objectToValidate.PropertyA) &&
            ValidateObjectPropertyB(objectToValidate.PropertyB, currentUserId);
    }

    public bool ValidateObjectPropertyB(long propertyB, long userId)
    {
        return validationResult;
    }
}

现在我的测试类ObjectServiceTest包含以下代码:

public class ObjectServiceTest
{
    var objectToValidate = new Object(validPropertyA, validPropertyB);

    using(var mock = new AutoMock.GetStrict())
    {
        var mockObjectService = new Mock<IObjectService>();
        mockObjectService.callBase = true;
        mockObjectService.Setup(s => s.ValidateObjectPropertyB(objectToValidate.PropertyB, _user.Id)).Returns(true);

        var service = mock.Create<ObjectService>();
        var result = service.ValidateObject(objectTovalidate);

        Assert.IsTrue(result);
    }
}

上述测试失败,因为resultfalse,而PropertyA成功 我做错了什么?

1 个答案:

答案 0 :(得分:0)

ValidateObject部分通过调用ValidateObjectPropertyB来工作。我假设您想要模拟第二种方法,以便您可以证明ValidateObject确实调用ValidateObjectPropertyB(提供!String.IsNullOrEmpty(objectToValidate.PropertyA)计算结果为true)

如果是这种情况,那么您正在测试实现细节,通常您不应该这样做。考虑一个带有两个整数值并返回它们的总和的函数,你要验证当这个函数被传递3和5它返回8时,你不应该通过使用特定的方法/类来测试它是否达到了这个答案。引擎盖,因为这与期望的结果无关,并且在将来你决定你希望重构你的代码时,即使代码仍然返回了期望的结果,测试也可能开始失败。

查看代码,似乎ValidateObject的返回值不直接依赖于对ValidateObjectPropertyB的方法调用,而是依赖于validationResult的值。必须设置此值才能正确测试ValidateObject。

实现所要求的一种方法是使ValidateObjectPropertyB成为虚拟,然后创建一个派生类来覆盖此方法以返回您想要的内容。但是我不建议仅仅为了单元测试而这样做。