我如何模拟或测试我的延迟评估/执行功能?

发布于 2024-09-02 06:07:05 字数 836 浏览 5 评论 0原文

我的应用程序堆栈中传递了域对象的 IQueryableIList 集合,这可以被视为奇怪的混合体。我试图尽可能多地维护“延迟查询”或“延迟加载”。我通过两种方式执行此操作:

  1. 使用 LinqToSql 数据层并通过存储库将 IQueryable 传递到我的应用程序层。
  2. 然后,在我的应用程序层传递 IList 之后,但对象/聚合图中的某些元素是 与委托“链接”,以便推迟其加载。有时,甚至委托内容也依赖于 IQueryable 源,并注入 DataContext

到目前为止这对我有用。

极其困难的是证明这种设计确实有效。 IE。如果我在某个地方击败了“懒惰”部分,并且我的评估/执行很早就发生了,那么整个事情就是浪费时间。我希望能够以某种方式进行 TDD。

我对委托或线程安全了解不多,因为它适用于作用于同一源的委托。我希望能够模拟 DataContext 并以某种方式跟踪延迟加载的两种方法(IQueryable的 SQL 和委托),以便我可以进行测试证明这两个函数都在应用程序/堆栈的不同级别/层上工作。

由于延迟对于设计具有任何价值至关重要,因此当我在给定级别(与实时实现分开)破坏设计时,我希望看到测试失败。这可能吗?

I have what could be seen as a bizarre hybrid of IQueryable<T> and IList<T> collections of domain objects passed up my application stack. I'm trying to maintain as much of the 'late querying' or 'lazy loading' as possible. I do this in two ways:

  1. By using a LinqToSql data layer and passing IQueryable<T>s through by repositories and to my app layer.
  2. Then after my app layer passing IList<T>s but where certain elements in the object/aggregate graph are 'chained' with delegates so as to defer their loading. Sometimes even the delegate contents rely on IQueryable<T> sources and the DataContext are injected.

This works for me so far.

What is blindingly difficult is proving that this design actually works. Ie. If i defeat the 'lazy' part somewhere and my evaluation/execution happens early then the whole thing is a waste of time. I'd like to be able to TDD this somehow.

I don't know a lot about delegates or thread safety as it applies to delegates acting on the same source. I'd like to be able to mock the DataContext and somehow trace both methods of deferring (IQueryable<T>'s SQL and the delegates) the loading so that i can have tests that prove that both functions are working at different levels/layers of the app/stack.

As it's crucial that the deferring works for the design to be of any value, i'd like to see tests fail when i break the design at a given level (separate from the live implementation). Is this possible?

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

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

发布评论

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

评论(2

别靠近我心 2024-09-09 06:07:05

morelinq 中,我们有一个所谓的“中断序列”来测试这一点。基本上,它是一个枚举器,每当枚举它时就会抛出异常。

它可以很简单:

internal sealed class BreakingSequence<T> : IEnumerable<T>
{
    public IEnumerator<T> GetEnumerator()
    {
        throw new InvalidOperationException();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

测试如下:

   [Test]
    public void XyzIsLazy()
    {
        var source = BreakingSequence<EntityClass>().AsQueryable();

        // inject it as your query source wherever appropriate
        var query = source.Where(x=> true);
        // does not throw, where does not enumerate the sequence
    }

At morelinq, we have a so called "breaking sequence" to test that. Basically, it is an enumerator that will throw an exception whenever it is enumerated.

It can be as easy as:

internal sealed class BreakingSequence<T> : IEnumerable<T>
{
    public IEnumerator<T> GetEnumerator()
    {
        throw new InvalidOperationException();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

A test for it looks like this:

   [Test]
    public void XyzIsLazy()
    {
        var source = BreakingSequence<EntityClass>().AsQueryable();

        // inject it as your query source wherever appropriate
        var query = source.Where(x=> true);
        // does not throw, where does not enumerate the sequence
    }
残疾 2024-09-09 06:07:05

我将以与约翰内斯·鲁道夫的回答类似的方式回答。听起来你正在思考正确的事情,想要对一些重要的事情进行测试,如果失败就很难追踪。

我绝对建议为此目的使用模拟。 Johannes 建议使用一个在枚举时抛出异常的对象。由于您的对象是模板化的,我相信您应该能够使用您想要的任何对象。模拟框架,例如 Rhino.Mocks(免费)或 TypeMock Isolator(昂贵),可能会非常有帮助。如果您还没有的话,我强烈建议您研究一下模拟框架。

有了模拟,您就可以评估在运行某些测试代码时操作应按特定顺序进行。您可以对模拟进行编程以记录发生的操作,然后在测试结束时检查记录。

I'm going to answer in a similar vein to what Johannes Rudolph answered. It sounds like you're thinking the right thing, wanting to have a test for something important that would be difficult to trace if it fails.

I would definitely suggest using a mock for this purpose. Johannes suggested an object that throws exception when it is enumerated. Since your object is templated, I believe you should be able to use whatever object you want. A mocking framework, such as Rhino.Mocks (free) or TypeMock Isolator (expensive), may be very helpful. I highly recommend looking into mocking frameworks if you haven't already.

With a mock in hand, you could evaluate that operations should take place in a certain order when you run certain test code. You could program your mock to record what operations take place and then check the recording at the end of the test.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文