gpt4 book ai didi

c# - Entity Framework 6 和 Moq4 : Is it possible to have a mocked DbSet retain added data for the duration of its scope?

转载 作者:行者123 更新时间:2023-11-30 22:05:38 24 4
gpt4 key购买 nike

背景: - 使用 EntityFramework 6 - 使用最小起订量 v4.2.1402.2112 - 使用 DbFirst 方法

不过,我一直在关注 EF6 Moq 演练(可在 here 中找到);我一直想知道是否可以让模拟的 DbSet 在其范围内保留添加到它的数据?

例如:

using Microsoft.VisualStudio.TestTools.UnitTesting; 
using Moq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;

namespace TestingDemo
{
[TestClass]
public class QueryTests
{
[TestMethod]
public void GetAllBlogs_orders_by_name()
{
var data = new List<Blog>
{
new Blog { Name = "BBB" },
new Blog { Name = "ZZZ" },
new Blog { Name = "AAA" },
}.AsQueryable();

var mockSet = new Mock<DbSet<Blog>>();
mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

var mockContext = new Mock<BloggingContext>();
mockContext.Setup(c => c.Blogs).Returns(mockSet.Object);

var service = new BlogService(mockContext.Object);
service.AddBlog("YYY", "http://blogs.msdn.com/yyyy");
var blogs = service.GetAllBlogs();

Assert.AreEqual(4, blogs.Count); // Fails because whilst the AddBlog is called, and we can verify this, the AsQueryable List doesn't retain the new data
Assert.AreEqual("AAA", blogs[0].Name);
Assert.AreEqual("BBB", blogs[1].Name);
Assert.AreEqual("YYY", blogs[2].Name);
Assert.AreEqual("ZZZ", blogs[3].Name);
}
}
}

是否可以保留添加的数据以便稍后在测试中查询?

最佳答案

您需要做的是对您希望修改集合的所有方法使用回调。动态代理中的回调是在调用方法时运行的代码,并且可以访问参数。

创建一个临时集合来保存数据(如示例代码中的 data)。然后实现一个回调(1):对于动态代理的每一个可以修改集合的方法。在这些回调中,修改您的临时集合 ( data )。然后在你的动态代理中,模拟 Count方法返回此集合中的计数 (data)。

您的临时收藏已创建:data .

(2)添加回调的方法是您的服务用于添加博客的方法,BlogService.AddBlog 我不使用 Moq4,所以我不会向您展示语法,但是 look here, in the callbacks section ,并使用此语法添加所需的回调。

模拟具有许多方法和属性以及复杂行为(如 DbSet<T>)的东西的问题是:

  • 您需要在动态代理中实现大量回调:如(1) 中所述,有多少方法可以修改集合?
  • 或者您需要了解被测代码的实现细节,以便仅实现必要的回调,如 (2) 哎呀!那太丑了。您可以实现一些有效的方法,但测试可能会失败,因为您没有模拟所需的方法。

要避免这个问题,您有两种解决方案。

  1. 创建一个接口(interface)来包装 EF 功能。模拟这个界面。该解决方案限制了模拟方法的数量
  2. 使用内存数据库作为后端,这样您的测试就像一个真实的数据库,您不需要模拟任何东西。您只需要为每个测试初始化​​内存中的数据库数据。 Look here ,但不要只看已接受的答案(顺便说一句,这不是最好的答案)。

关于c# - Entity Framework 6 和 Moq4 : Is it possible to have a mocked DbSet retain added data for the duration of its scope?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24258910/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com