簡體   English   中英

Mocking 使用 RhinoMocks 進行 nunit 測試的 ITable

[英]Mocking an ITable using RhinoMocks for nunit testing

我有一個接口,我針對它運行 linq 到 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()
    };

查詢運行良好。 我被困的地方是在編寫單元測試時。 如何獲取 function GetMyTable() 返回一個帶有一些假數據的模擬 object,圍繞這里的待辦事項:

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;
        }
 }

如果我正確理解你的問題,你可能想要生成 IMyDataContext 的模擬,而不是只為測試做你自己的實現。

在 IMyDataContext 模擬中,您可以像這樣設置期望:

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

您也可以在模擬表上設置期望值。 或者,您可以創建一個 class 的新實例,實現 ITable 接口,用內存中的測試數據填充該實例。

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接口,例如因為你想從表中添加或刪除行,你將想要創建你自己的抽象 class TestableTable 你可以擴展List (這樣它已經實現了IEnumerable )並提供所有IQueryable -methods經過:

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

現在只剩下ITable中的其他內容了。 這些很容易轉化為List -Methods,但.Commit() ,您可以保留抽象,然后可以將其存根和.AssertWasCalled(…)

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

希望有所幫助。

PS:我在為同一問題尋找標准解決方案時遇到了你的問題。 沒有找到任何東西,所以我實現了這個。

這是與 NSubstitute 一起使用的,但您可以針對 Rhino 進行調整。

    [TestMethod]
    public void Your_Test_Method()
    {
        var jobs = new List<JobInstance> { new JobInstance { JobInstanceId = 123 } };
        ITable<JobInstance> jobsTable = FakeTable(jobs);
        this.wfDataContext.JobInstances.Returns(jobsTable);
        ...
    }

    /// <summary>Sets up ITable substitution</summary>
    /// <typeparam name="T">Type of ITable set</typeparam>
    /// <param name="data">Data to work with</param>
    /// <returns>Substituted ITable set</returns>
    private static ITable<T> FakeTable<T>(List<T> data)
        where T : class
    {
        IQueryable<T> dataQueryable = data.AsQueryable();
        var fakeTable = Substitute.For<ITable<T>>();
        fakeTable.Provider.Returns(dataQueryable.Provider);
        fakeTable.Expression.Returns(dataQueryable.Expression);
        fakeTable.ElementType.Returns(dataQueryable.ElementType);
        fakeTable.GetEnumerator().Returns(dataQueryable.GetEnumerator());

        return fakeTable;
    }

我不知道 linq-to-sql 也不知道ITable 但是當我看到這個界面時,我真的懷疑你是否應該嘲笑它。 這太復雜了。 Mocking 它最終可能會編寫一個完整的數據庫模擬器,這顯然沒有意義。 單元測試應始終盡可能簡單。

我建議使用實現ITable 明確一點:不要編寫自己的實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM