【发布时间】:2014-08-28 02:07:42
【问题描述】:
我想测试一个方法在特定条件下向 DBSet 添加记录:
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() 并验证 [条件 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 的测试替身必须提供所用方法和属性的实现。”
【问题讨论】:
-
It.IsAny
() 验证是否通过?如果是这样,请检查 Id 的类型。如果没有,也许您需要在内部模拟而不是 mockDC 上设置 Add 方法。 -
它没有通过——我得到一个稍微不同的错误“预期在模拟上至少调用一次,但从未执行过”。我替换了行“mockDC.Setup(q => q.InternalTransactions.Add(It.IsAny
()));”使用“internals.Setup(q => q.Add(It.IsAny ()));” - 结果相同 -
一件事 - 如果 InternalTransactions 是一个属性,您需要use
SetupGet。根据 Adam 的说法,我相信Create和Add设置可能需要在internals上完成,而不是在mockDC上。 -
SetupGet 是在 mockDC 上还是在内部?
-
等等...这似乎做了一些事情。我将 Create() 的设置从 mockDC 更改为 internals 并且测试通过了!我需要进一步调查,看看这是否真的有效,但我认为我们走在正确的轨道上。
标签: c# entity-framework moq xunit