我正在为服务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);
}
}
上述测试失败,因为result
为false
,而PropertyA
成功
我做错了什么?
答案 0 :(得分:0)
ValidateObject部分通过调用ValidateObjectPropertyB来工作。我假设您想要模拟第二种方法,以便您可以证明ValidateObject确实调用ValidateObjectPropertyB(提供!String.IsNullOrEmpty(objectToValidate.PropertyA)计算结果为true)
如果是这种情况,那么您正在测试实现细节,通常您不应该这样做。考虑一个带有两个整数值并返回它们的总和的函数,你要验证当这个函数被传递3和5它返回8时,你不应该通过使用特定的方法/类来测试它是否达到了这个答案。引擎盖,因为这与期望的结果无关,并且在将来你决定你希望重构你的代码时,即使代码仍然返回了期望的结果,测试也可能开始失败。
查看代码,似乎ValidateObject的返回值不直接依赖于对ValidateObjectPropertyB的方法调用,而是依赖于validationResult的值。必须设置此值才能正确测试ValidateObject。
实现所要求的一种方法是使ValidateObjectPropertyB成为虚拟,然后创建一个派生类来覆盖此方法以返回您想要的内容。但是我不建议仅仅为了单元测试而这样做。