单元测试返回类型的选项我不能轻易创建

本文关键字:易创建 创建 不能 返回类型 选项 单元测试 | 更新日期: 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>

下面是修复它的一些可能性:

  • 在测试中更改dataMyTrickyClass<Record>(虽然我猜如果这是可能的,你已经做到了)
  • 使MyTrickyClass更容易构建,然后执行上述
  • 改变IRepository的接口,使其返回IQueryable而不是MyTrickyClass(这是最好的,如果它需要的是IQueryable)
  • 将存储库包装在一个层中,该层允许您包装返回值。这是另一层抽象,但如果你发现你不能改变存储库或MyTrickyClass,那么你可能想把自己从它隔离出来
  • 正如@Erik Dietrich建议的,你可以让MyTrickyClass实现一个接口。但是,您仍然无法使用IQueryable创建数据,因为强制转换将失败。但是,您可以创建一个ITrickyClass的模拟,或者创建一个实现接口的小存根类(如果MyTrickyClass是一个域对象,您可能会在很多地方使用它,因此手工编码的存根可能更有用)。