用于单元测试我无法轻松创建的返回类型的选项

发布于 2024-12-21 20:56:48 字数 984 浏览 1 评论 0原文

我需要对一个方法进行单元测试,该方法返回一个我无法轻易伪造或实例化的类型。该类型实现了 IQueryable 我最初认为我可以利用它来发挥我的优势,但目前我不知道如何使用。

例如:

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。如果我尝试将 data 转换为 MyTrickyClass 类型,则转换会失败。

所有这些都是有道理的,但这让我想知道正确的解决方案是什么。对于这种情况有哪些解决方法?我也许可以更改 MyTrickyClass,但理想情况下我想找到一个不影响它的解决方案。

I need to unit test a method that returns a type I can't easily fake or instantiate. The type implements IQueryable<T> which I originally thought I could use to my advantage, but I don't see how at this point.

For example:

public sealed class MyTrickyClass<T> : IQueryable<T>
{
    ...
}

public MyTrickyClass<T> GetData()
{
    return repository.GetAllData();
}

and my unit test

[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);

}

This won't compile because the return type of GetAllData() is MyTrickyClass<T>. If I try to cast data to a MyTrickyClass<Record> type, the cast fails.

All this makes sense, but it leaves me wondering what the right solution is. What are some workarounds for this kind of situation? I may be able to change the MyTrickyClass, but ideally I'd like to find a solution that leaves it alone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏雨凉 2024-12-28 20:56:48

您可以让 MyTrickyClass 实现接口 ITrickyClass,它继承自 IQueryable。这对你的类本身来说似乎是微乎其微的,而且你有一个很好的嘲笑接缝。

You could have MyTrickyClass<T> implement interface ITrickyClass<T>, which inherits from IQueryable<T>. That seems minimally invasive to your class itself, and you'd have a good seam for mocking.

天冷不及心凉 2024-12-28 20:56:48

测试中的 data 变量是 IQueryable,而不是 MyTrickyClass

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

  • 将测试中的 data 更改为 MyTrickyClass (尽管我猜测这是否可能,您已经完成了它)
  • 使 MyTrickyClass 更容易构造,然后执行上述操作
  • 更改 IRepository 的接口,以便它返回一个 IQueryable 而不是MyTrickyClass (如果它所需要的只是 IQueryable 的话,这是最好的)
  • 将存储库包装在一个层中,这样您还可以包装返回值。这是另一层抽象,但如果您发现无法更改存储库或 MyTrickyClass ,那么您可能希望将自己与它隔离正如
  • @Erik Dietrich 建议的那样,您可以使 MyTrickyClass 实现一个接口。但是,您仍然无法使用 IQueryable 创建数据,因为转换将会失败。不过,您可以创建一个 ITrickyClass 的模拟,或者创建一个实现该接口的小存根类(如果 MyTrickyClass 是一个域对象,您可能会使用它无论如何,在很多地方,所以手工编码的存根可能更有用)。

Your data variable in the test is an IQueryable<Record>, not a MyTrickyClass<Record>.

Here are some possibilities for fixing it:

  • Change data in the test to be a MyTrickyClass<Record> (though I'm guessing if this was possible you'd already have done it)
  • Make MyTrickyClass easier to construct, then do the above
  • Change the interface of IRepository so that it returns an IQueryable instead of a MyTrickyClass (which is best if all it needs is the IQueryable anyway)
  • Wrap the repository in a layer which lets you also wrap the return value. It's another layer of abstraction, but if you find you can't change the repository or MyTrickyClass then you probably want to be isolating yourself from it anyway
  • As @Erik Dietrich suggested, you could make MyTrickyClass implement an interface. However, you still won't be able to create data using an IQueryable as the cast will fail. You could create a mock of ITrickyClass instead, though, or create a little stub class that implements the interface (if MyTrickyClass is a domain object, you'll probably be using it in a lot of places anyway, so a hand-coded stub may be more useful).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文