【问题标题】:Mocking an ITable using RhinoMocks for nunit testing使用 Rhino Mocks 模拟表格进行单元测试
【发布时间】:2011-08-30 14:48:57
【问题描述】:

我有一个运行 linq to sql 查询的接口:

public interface IMyDataContext : IDisposable
{
    ITable<MyTable> GetMyTable();
}

在这个界面上,我正在运行一个 linq 查询:

var results = from table1 in _MyDataContext.GetMyTable() 
    group table1 by table1.Column1 into myGroup
    orderby myGroup.Count() descending 
    select new
    {
        Column1 = myGroup.Key,
        Count = myGroup.Count()
    };

查询运行良好。我被卡住的地方是在编写单元测试时。 如何让函数 GetMyTable() 返回一个带有一些假数据的模拟对象,围绕这里的待办事项:

public class MockMyContextWrapper : IMyDataContext
{
        public void Dispose()
        {

        }

        public ITable<MyTable> GetMyTable()
        {
            var table = MockRepository.GenerateMock<ITable<MyTable>>();

            //todo: code to return something so that the linq query fired on this table works

            return table;
        }
 }

【问题讨论】:

    标签: c# linq nunit rhino-mocks itable


    【解决方案1】:

    如果我正确理解了您的问题,您可能希望生成 IMyDataContext 的模拟,而不是仅为测试执行您自己的实现。

    在 IMyDataContext 模拟中,您可以像这样设置期望:

    var dataContext = MockRepository.GenerateMock<IMyDataContext>();
    var table = MockRepository.GenerateMock<ITable<MyTable>>();
    dataContext.Expect(x => x.GetMyTable()).Return(table);
    

    您也可以在模拟表上设置期望值。或者,您可以创建一个实现 ITable 接口的类的新实例,用内存中的测试数据填充该实例。

    【讨论】:

      【解决方案2】:

      我不知道 linq-to-sql,也不知道 ITable。但是当我看到这个界面时,我真的怀疑你是否应该模拟它。这太复杂了。模拟它最终可能会编写一个完整的数据库模拟器,这绝对没有意义。单元测试应该尽可能简单。

      我建议使用实现ITable 的真实类。说清楚:不要编写自己的实现。

      【讨论】:

        【解决方案3】:

        ITable 包含 3 个不同的接口:IEnumerableIQueryableITable 中的其他内容。您所做的只是查询可以使用IQueryable 的表并将其传递给模拟/存根:

         IQueryable<MyTable> testTable = new[]{new MyTable{…}, new MyTable{…}, …, new MyTable{…}}.AsQueryable();
         myMock.Stub(x => x.GetMyTable()).Return(testTable);
        

        每个new MyTable{…} 将代表表中的一行。

        如果/一旦您需要完整的ITable 接口,例如因为您想从表中添加或删除行,您需要创建自己的抽象类 TestableTable,您可以扩展List(这样它已经实现了IEnumerable)并通过以下方式提供所有IQueryable-方法:

         public SomeType SomeMethodFromIQueryable(…)
         {
              return this.AsQueryable().SomeMthodFromIQueryable(…);
         }
        

        现在只剩下ITable 中的其他内容了。这些很容易翻译成List-方法,但.Commit() 除外,您可以留下抽象然后可以存根它和.AssertWasCalled(…) 它。

         var myMock = MockRepository.GenerateStub<TestableTable<MyTable>>(){ new MyTable{…}, …};
         …
         myMock.AssertWasCalled(x => x.Commit());
        

        希望对您有所帮助。

        P.S.:我在为同一问题寻找标准解决方案时遇到了您的问题。没有找到任何东西,所以我实现了这个。

        【讨论】:

          猜你喜欢
          • 2011-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多