我有一个单元测试,用于验证函数是否只向一个Entity Framework数据集添加了一条记录,如下所示:
var internals = new Mock<DbSet<InternalTransaction>>();
internals.Setup(q => q.Create()).Returns(new InternalTransaction());
var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
// Removed: set up some data for my test
mockDC.Object.DoSomeFunction(data);
internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());
由于我对此上下文进行了大量测试,因此我尝试将模拟内容提取到单独的类中,如下所示:
public static class DataContext_Creators
{
public static Mock<IDataContext> CreateMockContext()
{
var internals = CreateMockDataSet<InternalTransaction>();
var externals = CreateMockDataSet<ExternalTransaction>();
var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
mockDC.Setup(q => q.ExternalTransactions).Returns(externals.Object);
return mockDC;
}
private static Mock<DbSet<T>> CreateMockDataSet<T>() where T : class, new ()
{
var mockDataSet = new Mock<DbSet<T>>();
mockDataSet.Setup(q => q.Create()).Returns(new T());
// some other stuff, Provider, GetEnumerator, etc
return mockDataSet;
}
}
...并将我的测试更改为:
mockContext = Common.DataContext_Creators.CreateMockContext();
context = mockContext.Object;
// Removed: set up some data for my test
context.Object.DoSomeFunction(data);
//internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());
但是现在我再也无法访问“内部”了,我该如何处理.Verify()语句? context.InternalTransactions不起作用,因为它返回“internals.Object”(我正在测试的方法需要它才能工作)。
答案 0 :(得分:1)
通过使用Mock.Get()方法,您可以再次从该对象中重新获得它的Mock对象。看一下例子:
public class Entity
{
public virtual int Id { get; set; }
public virtual int? ParentId { get; set; }
}
static void Main(string[] args)
{
Entity entity = Mock.Of<Entity>();
var mock = Mock.Get<Entity>(entity);
mock.Setup(e => e.ParentId).Returns(11);
var result = entity.ParentId;
// now result == 11
}
你可以在你的internals.Object
上使用Mock.Get方法答案 1 :(得分:0)
创建一个包含2个属性的新实用程序类:
Mock<IDataContext> DbContextMock
Mock<DbSet<InternalTransaction>> InternalTransMock
让您的Utility函数返回此新对象,以便您的测试可以访问这两个对象。