这是测试场景。
当孩子年龄超过3岁时,IsAdult == true
。
我想用Moq进行测试。但失败是因为Age
总是根据设置
2
我该如何测试?嘲笑一个坏主意?
使用调试方法或蛮力不是......
public class Kid
{
public virtual float Age { get; private set; } = 0;
public bool IsAdult { get; private set; }
private float _ageIncreasePerHour = 1;
public void OnHourPass()
{
Age += _ageIncreasePerHour;
if (Age >= 3)
{
IsAdult = true;
}
}
public void Debug_SetAge(float newAge)
{
Age = newAge;
}
}
public class Test_Kid
{
//fail. how can i mocking?
[Test]
public void WhenAgeOver3_Kid_IsAdult_UseMocking()
{
var mockKid = new Mock<Kid> { CallBase = true };
mockKid.Setup(x => x.Age).Returns(2);
Assert.AreEqual(2, mockKid.Object.Age);
mockKid.Object.OnHourPass();
Assert.AreEqual(3, mockKid.Object.Age); // but 2.
Assert.AreEqual(true, mockKid.Object.IsAdult); // but false.
}
//success. but not intended. Debug-Method is anti pattern!
[Test]
public void WhenAgeOver3_Kid_IsAdult_UseDebugMethod()
{
var newKid = new Kid();
newKid.Debug_SetAge(2);
newKid.OnHourPass();
Assert.AreEqual(true, newKid.IsAdult);
}
}
答案 0 :(得分:1)
Moq无法使用Age
属性的私有 setter,因此在使用Moq时会遇到困难,因为如果您尝试将属性的setter设置为记录,它会抛出异常行为(副作用)。
但是,您可以完全避免使用Moq,并使用PrivateObject Class
作为被测对象的包装来设置值。
使用PrivateObject.SetProperty
,您可以设置测试的初始值,然后根据需要进行测试。
假设
public class Kid {
public virtual float Age { get; private set; }
public bool IsAdult { get; private set; }
private float _ageIncreasePerHour = 1;
public void OnHourPass() {
Age += _ageIncreasePerHour;
if (Age >= 3) {
IsAdult = true;
}
}
}
测试看起来像这样......
public void _WhenAgeOver3_Kid_IsAdult() {
//Arrange
var initialAge = 2;
var expectedAge = initialAge + 1;
var kid = new Kid();
var wrapper = new PrivateObject(kid);
wrapper.SetProperty("Age", initialAge);
Assert.AreEqual(initialAge, kid.Age);
//Act
kid.OnHourPass();
//Assert
Assert.AreEqual(expectedAge, kid.Age); // should be 3.
Assert.AreEqual(true, kid.IsAdult); // should be true.
}
如果您能够改变主题,另一个选择是重构主题以在其构造函数中采用可选参数来设置初始Age
public class Kid {
public Kid(int initialAge = 0) {
Age = initialAge;
}
public virtual float Age { get; private set; }
public bool IsAdult { get; private set; }
private float _ageIncreasePerHour = 1;
public void OnHourPass() {
Age += _ageIncreasePerHour;
if (Age >= 3) {
IsAdult = true;
}
}
}
这样就可以将测试重构为....
public void _WhenAgeOver3_Kid_IsAdult() {
//Arrange
var initialAge = 2;
var expectedAge = initialAge + 1;
var kid = new Kid(initialAge);
Assert.AreEqual(initialAge, kid.Age);
//Act
kid.OnHourPass();
//Assert
Assert.AreEqual(expectedAge, kid.Age); // should be 3.
Assert.AreEqual(true, kid.IsAdult); // should be true.
}