问题描述
我有如下所示的服务 CarTankService
.它有我想测试的 Add
方法.更详细地说,我想检查是否会到达 AddTank
(inside Add)
.
I have service CarTankService
as shown below. It has Add
method which i want to test. To be more detailed i would like to check whether AddTank
(inside Add)
will be reached.
public class CarTankService : ICarTankService
{
private readonly ITankQuery _tankQuery;
private readonly CarClient _carClient;
public CarTankService(ITankQuery tankQuery)
{
_tankQuery = tankQuery;
_carClient = new CarClient();
}
public ObservableCollection<CarTank> GetTanks() => _carClient.Tanks;
public void GenerateNewList() => _carClient.GenerateNewTanksList();
public virtual void Add(CarTank tank)
{
if (_tankQuery.isExist(tank.Number)) throw new OwnException()
_carClient.AddTank(tank);
}
public virtual void Remove(CarTank tank) => _carClient.RemoveCarTank(tank);
}
这是我的测试方法类:
[TestFixture]
class CarTankServiceTests
{
private Mock<ITankQuery> TankQuery { get; set; }
private ICarTankService CarTankService { get; set; }
private Mock<CarClient> CarClient { get; set; }
[SetUp]
public void SetUp()
{
TankQuery = new Mock<ITankQuery>();
CarClient = new Mock<CarClient>();
CarTankService = new CarTankService(TankQuery.Object);
}
[Test]
public void Add_NotExistReferenceNumber_AddTankReached()
{
TankQuery.Setup(uow => uow.isExist(It.IsAny<int>())).Returns(false);
CarTankService.Add(new CarTank());
CarClient.Verify(uow => uow.AddTank(It.IsAny<ClientTank>()),Times.Once);
}
}
CarClient.Verify
for AddTank
在测试中总是显示 0 发生
,在这种情况下这是不正确的.我不确定,但我认为这是因为 CarClient
模型类,因为它没有直接注入我的服务,它总是显示 0.我对吗?有没有测试的选项?
CarClient.Verify
for AddTank
always show it was 0 occurence
in test, which in this case is not true. I am not sure but I think it's because CarClient
model class because it's not injected directly insdie my service it always shows 0. AM i right? Is there any option to test it?
推荐答案
如果你模拟你的 CarClient
你必须设置你想要在你的测试中使用的所有方法(这里 AddTank
代码>).在您的代码中,我们有两个 CarClient
实例,一个在您的测试中被模拟,另一个在您的 CarTankService
构造函数中初始化.因此,您在验证模拟的情况时调用了后一种情况.
If you mock your CarClient
you have to setup all methods you want to use in your test (here AddTank
). In you code we have two CarClient
instances, one is mocked in your test and another is initialized in your constructor of CarTankService
. So, you are calling the latter case while verifying the mocked one.
如果将 CarClient
转换为接口并注入它,解决方案是这样的:
If you convert the CarClient
to an interface and inject it, The solution is something like this:
[TestFixture]
class CarTankServiceTests
{
private Mock<ITankQuery> TankQuery { get; set; }
private ICarTankService CarTankService { get; set; }
private Mock<CarClient> CarClient { get; set; }
[SetUp]
public void SetUp()
{
TankQuery = new Mock<ITankQuery>();
CarClient = new Mock<CarClient>();
CarTankService = new CarTankService(TankQuery.Object);
}
[Test]
public void Add_NotExistReferenceNumber_AddTankReached()
{
TankQuery.Setup(uow => uow.isExist(It.IsAny<int>())).Returns(false);
CarTankService.Add(new CarTank());
CarClient.Setup(a=>a.AddTank(/*write you loginc*/));
CarClient.Verify(uow => uow.AddTank(It.IsAny<ClientTank>()),Times.Once);
}
}
这里有更多解释:
当您在测试中编写 CarTankService = new CarTankService(TankQuery.Object);
时,它会在您的类上创建一个新实例 (_carClient = new CarClient();
),所以该类有它自己的实例,而测试类也有它自己的实例 (CarClient = new Mock();
) 被模拟.这行代码 CarTankService.Add(new CarTank());
将坦克添加到类的实例中,而在您的测试中,您正在验证没有坦克的测试类的实例(CarClient.Verify(uow => uow.AddTank(It.IsAny()),Times.Once);
).
When you write CarTankService = new CarTankService(TankQuery.Object);
in your test, it creates a new instance on your class (_carClient = new CarClient();
), so the class has it's own instance, while the test class has it own too (CarClient = new Mock<CarClient>();
) which is mocked. This line of code CarTankService.Add(new CarTank());
adds the tank to the instance of class, while in your test, you are verifying the instance of test class which has no tank (CarClient.Verify(uow => uow.AddTank(It.IsAny<ClientTank>()),Times.Once);
).
这篇关于如何使用未传递给真实对象的模拟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!