0

假设我有一项服务

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 没用。但是我使用存根然后单元测试将失败,因为它应该。

那么什么时候模拟,什么时候不模拟?

4

2 回答 2

4

所以我的 PriceCalculatorService_GetPrice_Test 没用。

不,这不对。它正在测试 的代码GetPrice,并且测试 的代码GetPrice。对我来说似乎很合理。

这种方法没有太多要测试的东西,但你正在测试它。如果您没有三次使用相同的参数会更好(例如,使用 1、2、3 会更好)但您正在测试它。

没有理由仅仅因为接口的实现发生了变化而中断测试。你抓住了对AreaServicein的变化AreaService_GetArea_Test(),这确实是你应该抓住它的地方。

于 2012-08-21T21:23:34.390 回答
2

PriceCalculatorService_GetPrice_Test正在测试GetPrice。它正在测试的返回值GetPrice是否_areaService.CalculateAreaTimesX(x, y, times)相乘price。这就是测试的意义。所以它根本没有用。

GetPrice应该取决于 的结果CalculateAreaTimesX,而不是该方法的逻辑。因此,无论模拟返回什么,都可以进行测试。

于 2012-08-22T06:19:26.850 回答