在模拟中测试多线程服务方法
本文关键字:服务 方法 多线程 测试 模拟 | 更新日期: 2023-09-27 18:06:56
例如,如果我给他n块来自不同线程的数据,我想测试我的多线程方法调用存储库方法n次的事实。当然,模拟不是线程安全的,甚至不应该是。
[Test]
public void CanSaveCustomersInParallel()
{
var customers = new List<List<Customer>>
{
new List<Customer>
{
new Customer {FirstName = "FirstName1"},
new Customer {FirstName = "FirstName2"}
},
new List<Customer>
{
new Customer {FirstName = "FirstName3"},
new Customer {FirstName = "FirstName4"}
}
};
_serviceCustomers.ParallelSaveBatch(customers);
_repoCustomers
.Verify(x => x.SaveBatch(It.IsAny<List<Customer>>()), Times.Exactly(2));
}
当然,这个测试有时会失败,有时不会。但这在本质上是不正确的。你能告诉我怎么重写吗?
下一个存根成功了:
internal class ServiceStub: Service<DummyEntity>
{
private int _count;
public int Count
{
get { return _count; }
}
public override void SaveBatch(IEnumerable<object> entities)
{
lock(this)
{
_count++;
}
}
public ServiceStub(IRepository<DummyEntity> repository):base(repository)
{
_count = 0;
}
}
单元测试从另一个方向看:
[Test]
public void CanSaveCustomersInParallel()
{
var service = new ServiceStub(new DummyRepository());
var customers = new List<List<Customer>>
{
new List<Customer>
{
new Customer {FirstName = "FirstName1"},
new Customer {FirstName = "FirstName2"}
},
new List<Customer>
{
new Customer {FirstName = "FirstName3"},
new Customer {FirstName = "FirstName4"}
}
};
service.ParallelSaveBatch(customers);
Assert.AreEqual(service.Count, customers.Count);
}
关于不稳定Moq行为的更多信息在这里
在版本<= 4.0中遇到的典型问题包括随机NullReferenceException
或IndexOutOfRangeException
,以及mock.Verify(<>, Times.Exactly(N))
失败(通常计数不足)。在4.1版本中,这些问题似乎已经
Edit根据下面@Danny的评论,请注意4.1中所做的更改包括锁定Mock,如果需要测试代码的并行性,这没有多大用处。
设计更改可以简化此测试。创建一个执行实际工作的SaveWorker,以及一个在另一个线程上执行SaveWork工作的代理(相同的抽象)。然后一个SaveWorkerFactory返回一个ThreadedSaveWorker,给定一个客户。最后,将SaveWorkerFactory的Mock注入_serviceCustomers,并验证它是否执行了这两个调用。