2014-07-07 63 views
4

我想要測試的方法在一定條件下將記錄添加到一個DBSet:C#起訂量實體框架6數據上下文添加操作

public static void AddTriggeredInternalTransactions(IDataContext dc, ExternalTransaction transaction) 
{ 
    if (transaction [meets condition A]) 
     dc.InternalTransactions.CreateInverseTransaction(transaction); 

    // do other stuff under other conditions 
} 

private static void CreateInverseTransaction(this IDbSet<InternalTransaction> transactions, ExternalTransaction from) 
{ 
    var internalTransaction = transactions.Create(); 
    from.CopyToInternalTransaction(internalTransaction); 
    transactions.Add(internalTransaction); 
} 

現在,我已經有CopyToInternalTransaction測試()。我只需要調用AddTriggeredInternalTransactions()並驗證[condition A]導致新記錄被添加)。

我從http://msdn.microsoft.com/en-us/data/dn314429.aspx開始,然後使用其他Google和StackOverflow搜索。在處理我的「真實」測試之前,我試圖做一個簡單的測試來驗證記錄是否已經添加到數據集中,但我堅持這一點。任何人都可以指出我的缺陷?

var internals = new Mock<DbSet<InternalTransaction>>(); 
var theData = new List<InternalTransaction>().AsQueryable(); 

internals.As<IQueryable<InternalTransaction>>().Setup(m => m.Provider).Returns(theData.Provider); 
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.Expression).Returns(theData.Expression); 
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.ElementType).Returns(theData.ElementType); 
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.GetEnumerator()).Returns(theData.GetEnumerator()); 

var mockDC = new Mock<IDataContext>(); 
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object); 
mockDC.Setup(q => q.InternalTransactions.Create()).Returns(new InternalTransaction()); 
mockDC.Setup(q => q.InternalTransactions.Add(It.IsAny<InternalTransaction>())); 

var it = mockDC.Object.InternalTransactions.Create(); 
it.Id = "123"; 
mockDC.Object.InternalTransactions.Add(it); 

internals.Verify(e => e.Add(It.Is<InternalTransaction>(d => d.Id == "123")), Times.Once()); 
//or: Assert.Equal(1, mockDC.Object.InternalTransactions.Count()); 

此測試失敗:在模擬預期調用一次,但是0次:E => e.Add(It.Is(d => d.Id == 「123」))不能設置配置。沒有執行調用。

如果使用Assert語句,則會失敗,並顯示NotImplementedException:「成員IQueryable.Provider尚未在繼承自DbSet1的類型DbSet〜1Proxy_1上實現.DbSet1的測試雙重必須提供方法和屬性的實現用過的。」

+1

是否驗證通與It.IsAny ()?如果是這樣,請檢查Id的類型。如果沒有,也許你需要在你的內部模擬器上設置Add方法而不是mockDC。 – Adam47

+0

它沒有通過 - 我得到了一個稍微不同的錯誤:「模擬期望的調用至少有一次,但從未執行過」。我替換了行「mockDC.Setup(q => q.InternalTransactions.Add(It.IsAny ()));」與「internals.Setup(q => q.Add(It.IsAny ()));」 - 相同的結果 –

+0

有一件事 - 如果InternalTransactions屬性,您需要[使用'SetupGet'](http://stackoverflow.com/q/12141799/314291)。根據Adam的說法,我認爲'Create'和'Add'設置可能需要在'internals'上完成,而不是在'mockDC'上完成。 – StuartLC

回答

1

後由亞當和Stuart加上進一步的試驗評價,我能到我的測試案例減少以下工作的測試用例:

var internals = new Mock<DbSet<InternalTransaction>>(); 
var mockDC = new Mock<IDataContext>(); 

mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object); 
internals.Setup(q => q.Create()).Returns(new InternalTransaction()); 

var transaction = new ExternalTransaction { [set criteria for Condition A] }; 

SomeBusinessObject.AddTriggeredInternalTransactions(mockDC.Object, transaction); 

// verify the Add method was executed exactly once 
internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());