代码之家  ›  专栏  ›  技术社区  ›  Matt Kocaj

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

  •  6
  • Matt Kocaj  · 技术社区  · 15 年前

    我有一种可以被看作是 IQueryable<T> IList<T> 域对象集合传递给了我的应用程序堆栈。我正在尽可能地维护“延迟查询”或“延迟加载”。我有两种方式:

    1. 通过使用LinqToSQL数据层并传递 可查询 通过存储库和我的应用层。
    2. 然后在我的应用程序层通过之后 ILIST & T;T & GT; 但对象/聚合图中的某些元素 'chained' with delegates 以便推迟装货。有时甚至代表的内容也依赖于 可查询 来源与 DataContext 注入。

    到目前为止这对我有效。

    令人眼花缭乱的困难是要证明这个设计确实有效。也就是说,如果我在某个地方击败了“懒惰”部分,并且我的评估/执行提前发生,那么整个过程就是在浪费时间。我希望能以某种方式进行TDD。

    我不太了解委托或线程安全,因为它适用于在同一个源上工作的委托。我想能够嘲笑 数据上下文 以某种方式追踪两种延迟方法( 可查询 的SQL和委托)加载,这样我就可以进行测试,证明这两个函数都在应用程序/堆栈的不同级别/层上工作。

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

    2 回复  |  直到 15 年前
        1
  •  4
  •   Johannes Rudolph    15 年前

    AT 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
        }
    
        2
  •  2
  •   Vivian River    15 年前

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

    我肯定会建议为此使用模拟模型。Johannes建议使用一个在枚举异常时引发异常的对象。因为你的对象是模板化的,我相信你应该能够使用任何你想要的对象。模拟框架,如Rhino.Mocks(免费)或TypeMock Isolator(昂贵),可能非常有用。如果您还没有,我强烈建议您研究模拟框架。

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