如何使用未传递给真实对象的模拟
How to use mock which is not passed to real object
我有如下所示的服务 CarTankService
。它有我想测试的 Add
方法。更详细地说,我想检查是否会达到 AddTank
(inside Add)
。
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);
}
这是我的测试方法class:
[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
对于 AddTank
总是显示它在测试中是 0 occurence
,在这种情况下是不正确的。我不确定,但我认为这是因为 CarClient
模型 class 因为它没有直接注入我的服务,它总是显示 0。我对吗?有什么选项可以测试吗?
如果您模拟 CarClient
,则必须设置要在测试中使用的所有方法(此处 AddTank
)。在您的代码中,我们有两个 CarClient
实例,一个在您的测试中被模拟,另一个在您的 CarTankService
的构造函数中初始化。因此,您在验证模拟的情况时调用了后一种情况。
如果将CarClient
转换为接口注入,解决方法如下:
[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);
时,它会在您的 class (_carClient = new CarClient();
) 上创建一个新实例,因此 class 有自己的实例,而测试 class 也有它自己的 (CarClient = new Mock<CarClient>();
),这是被嘲笑的。这行代码 CarTankService.Add(new CarTank());
将坦克添加到 class 的实例,而在您的测试中,您正在验证没有坦克 (CarClient.Verify(uow => uow.AddTank(It.IsAny<ClientTank>()),Times.Once);
) 的测试实例 class .
我有如下所示的服务 CarTankService
。它有我想测试的 Add
方法。更详细地说,我想检查是否会达到 AddTank
(inside Add)
。
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);
}
这是我的测试方法class:
[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
对于 AddTank
总是显示它在测试中是 0 occurence
,在这种情况下是不正确的。我不确定,但我认为这是因为 CarClient
模型 class 因为它没有直接注入我的服务,它总是显示 0。我对吗?有什么选项可以测试吗?
如果您模拟 CarClient
,则必须设置要在测试中使用的所有方法(此处 AddTank
)。在您的代码中,我们有两个 CarClient
实例,一个在您的测试中被模拟,另一个在您的 CarTankService
的构造函数中初始化。因此,您在验证模拟的情况时调用了后一种情况。
如果将CarClient
转换为接口注入,解决方法如下:
[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);
时,它会在您的 class (_carClient = new CarClient();
) 上创建一个新实例,因此 class 有自己的实例,而测试 class 也有它自己的 (CarClient = new Mock<CarClient>();
),这是被嘲笑的。这行代码 CarTankService.Add(new CarTank());
将坦克添加到 class 的实例,而在您的测试中,您正在验证没有坦克 (CarClient.Verify(uow => uow.AddTank(It.IsAny<ClientTank>()),Times.Once);
) 的测试实例 class .