单元测试返回类型的选项我不能轻易创建
本文关键字:易创建 创建 不能 返回类型 选项 单元测试 | 更新日期: 2023-09-27 18:18:05
我需要对一个方法进行单元测试,该方法返回一个我不能轻易伪造或实例化的类型。该类型实现了IQueryable<T>
,我最初认为我可以利用它来发挥我的优势,但我不知道在这一点上如何使用。
public sealed class MyTrickyClass<T> : IQueryable<T>
{
...
}
public MyTrickyClass<T> GetData()
{
return repository.GetAllData();
}
和我的单元测试
[Test Method]
public void CanGetData()
{
var data = (new List<Record>() { new Record() }).AsQueryable();
var mockRepository = new Mock<IRepository<Record>>();
mockRepository.Setup(s => s.GetAllData()).Returns(data);
MyService service = new MyService(mockRepository.Object);
var result = service.GetData();
Assert.IsNotNull(result);
}
这不会编译,因为GetAllData()的返回类型是MyTrickyClass<T>
。如果我尝试将data
转换为MyTrickyClass<Record>
类型,则转换失败。
所有这些都有道理,但它让我想知道正确的解决方案是什么。对于这种情况有什么变通办法?我可能能够改变MyTrickyClass,但理想情况下,我想找到一个解决方案,让它单独。
您可以让MyTrickyClass<T>
实现接口ITrickyClass<T>
,它继承自IQueryable<T>
。这似乎对您的类本身具有最小的侵入性,并且您将有一个很好的嘲讽接缝。
测试中的data
变量是IQueryable<Record>
,而不是MyTrickyClass<Record>
。
下面是修复它的一些可能性:
- 在测试中更改
data
为MyTrickyClass<Record>
(虽然我猜如果这是可能的,你已经做到了) - 使
MyTrickyClass
更容易构建,然后执行上述 - 改变
IRepository
的接口,使其返回IQueryable
而不是MyTrickyClass
(这是最好的,如果它需要的是IQueryable
) - 将存储库包装在一个层中,该层允许您包装返回值。这是另一层抽象,但如果你发现你不能改变存储库或
MyTrickyClass
,那么你可能想把自己从它隔离出来 - 正如@Erik Dietrich建议的,你可以让MyTrickyClass实现一个接口。但是,您仍然无法使用
IQueryable
创建数据,因为强制转换将失败。但是,您可以创建一个ITrickyClass
的模拟,或者创建一个实现接口的小存根类(如果MyTrickyClass
是一个域对象,您可能会在很多地方使用它,因此手工编码的存根可能更有用)。