【发布时间】:2012-08-21 21:19:27
【问题描述】:
假设我有一个服务
public interface IAreaService
{
int CalculateArea(int x,int y);
int CalculateAreaTimesX(int x, int y, int ammount);
}
public class AreaService : IAreaService
{
public int CalculateArea(int x,int y)
{
return x*y;
}
public int CalculateAreaTimesX(int x, int y, int ammount)
{
return CalculateArea(x, y)*ammount;
}
}
配合相关的单元测试
[TestMethod]
public void AreaService_GetArea_Test()
{
AreaService service = new AreaService();
int expected = 9;
int actual = service.CalculateArea(3, 3);
Assert.AreEqual(expected,actual,"The Calculate area does not work as expected");
}
[TestMethod]
public void AreaService_GetAreaMultiplyByX_TestTrueValue()
{
AreaService service = new AreaService();
int expected = 27;
int actual = service.CalculateAreaTimesX(3, 3, 3);
Assert.AreEqual(expected,actual);
}
好的,在运行单元测试之后。我确信我的方法是有效的,生活应该很棒。
但是现在我想在另一个类中使用 IAreaService,这就是我失去光的地方。这是另一个类的实现。
public class PriceCalculatorService
{
private readonly IAreaService _areaService;
public PriceCalculatorService(IAreaService areaService)
{
_areaService = areaService;
}
public double GetPrice(int x, int y, int times, double price)
{
return _areaService.CalculateAreaTimesX(x, y, times)*price;
}
}
如果我运行以下单元测试(我的想法可能在这里模拟错误,这就是问题所在。
[TestMethod]
public void PriceCalculatorService_GetPrice_Test()
{
var IAreaServiceMock = new Mock<IAreaService>();
IAreaServiceMock.Setup(ism => ism.CalculateAreaTimesX(2, 2, 2)).Returns(8);
PriceCalculatorService priceCalc = new PriceCalculatorService(IAreaServiceMock.Object);
double expected = 20;
double actual = priceCalc.GetPrice(2, 2, 2, 2.50);
Assert.AreEqual(expected,actual);
}
问题
当我运行上面提到的所有单元测试时,一切都很好。他们都通过了。但是让我们说我出于某种原因需要将 AreaService.Calculate() 方法更改为以下
public int CalculateArea(int x,int y)
{
return x*y+2;
}
这意味着我的单元测试“AreaService_GetArea_Test()”将失败,就像它应该的那样,但是由于“PriceCalculatorService_GetPrice_Test()”测试中使用的模拟仍然会通过,因为看起来当你模拟一个服务时,然后不使用实际代码(显然)。所以我的 PriceCalculatorService_GetPrice_Test 没用。但是我使用存根然后单元测试将失败,因为它应该。
那么什么时候模拟,什么时候不模拟?
【问题讨论】:
-
但这就是测试units的想法。您正在孤立地测试单独的单元。你的
AreaService_GetArea_Test会失败,这才是最重要的——你会立即看到哪个单元不能正常工作。如果它导致 10 次级联失败并且您仍然必须调试整个代码以识别“是谁的错”,那会更好吗?它不会违背单元测试的目的吗? :) -
是的,光线正在缓慢但肯定地亮起。在您之前刚刚解决问题之后,以这种方式做事是一个非常大的思维转变。但我相信这是值得的。谢谢。
标签: unit-testing moq