gpt4 book ai didi

c# - 模拟 DbContext - 无法插入新对象

转载 作者:行者123 更新时间:2023-11-30 12:58:36 25 4
gpt4 key购买 nike

https://msdn.microsoft.com/en-us/data/dn314429.aspx

我正在尝试使用类似于上面链接中的查询场景的代码。EF 6.1 + 最小起订量。它适用于像这样的预填充数据(我可以毫无问题地查询它们):

_context = new Mock<MyContext>();

IQueryable<users> users = new List<users>
{
new users{id = 1, email = "test@test.pl", password = "test", created = DateTime.Now, modified = DateTime.Now},
new users{id = 2, email = "test2@test.pl", password = "test", created = DateTime.Now, modified = DateTime.Now},
}.AsQueryable();
var mockUsers = new Mock<DbSet<users>>();
mockUsers.As<IQueryable<users>>().Setup(m => m.Provider).Returns(users.Provider);
mockUsers.As<IQueryable<users>>().Setup(m => m.Expression).Returns(users.Expression);
mockUsers.As<IQueryable<users>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockUsers.As<IQueryable<users>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());

_context.Setup(m => m.users).Returns(mockUsers.Object);

但是当我尝试在我的测试方法中添加新对象时,它不起作用:

[TestMethod]
public void AddUser()
{
_context.Object.users.Add(new users { email = "test3@test.pl", password = "test", created = DateTime.Now, modified = DateTime.Now });
_context.Object.SaveChanges();
var count = _context.Object.users.Count();
Assert.AreEqual(3, count); // count == 2 instead 3
}

是否可以修改它,以便我的模拟上下文实际应用 SaveChanges?我的想法是否正确,或者由于某种原因这种方法是错误的?

如果我使用非查询方法,我将无法使用:

mockContext.Object.users.Count()

假设我有测试方法,片段如下:

 context.cards.Add(card);
context.SaveChanges();
SetCardForUser(card.id, user);

protected void SetCardForUser(long cardId, users user)
{
user.card_id = cardId;
context.SaveChanges();
}

我需要在将对象插入数据库后返回 card.id。我是否应该严格遵守 SRP 并采用只做一件事的方法?

我如何在只有 AddCardAndStartAuthCharge 是公共(public)的而其他方法是 protected 情况下测试这个方法? :

public async Task<long> AddCardAndStartAuthCharge(CardModel model, string username)
{
var hash = await GetHashForCardAuth(model);
var CardWithId = AddCardToDatabase(model, username);
long chargeId = AddHashToCard(CardWithId, hash);
return chargeId;
}

最佳答案

如评论中所述,使用 EntityFramework 时完全不需要自己管理 ID。观察这段代码:

MyContext context = new MyContext();
User user = new User() { Name = "Name1" };
context.Users.Add(user);
context.SaveChanges();
Console.WriteLine(user.Id);

执行 SaveChanges 后,系统会自动获得一个 ID。因此,可以很容易地重构像您另一个问题中的片段这样的片段。

//Old
public CardModel AddCard(CardModel model, string username)
{
var user = context.users.Where(x => x.email.ToLower() == username.ToLower()).First();
var card = new cards()
{
created = DateTime.Now,
modified = DateTime.Now,
name = model.Name,
type = model.CardType,
user_id = user.id
};
context.cards.Add(card);
context.SaveChanges();
model.Id = card.id;
return model;
}

//New
public CardModel AddCard(CardModel model, string username)
{
var user = context.users.Where(x => x.email.ToLower() == username.ToLower()).First();
user.Cards.Add(model)
user.SaveOrUpdate()
return model;
}

请注意,在任何时候都不需要像 model.Id = card.id 这样的东西!

如果不对现有模型进行一些更改,这很可能无法工作。您必须配置 EntityFramework 以将模型中的更改正确地级联到所有子模型(例如,如果删除了 User,则删除所有 Cards)。

现在,回答您的问题。如果您根据上述重构代码,您将永远不会依赖 SaveChanges() 和上下文中包含的 DBSet 来提供您的模型。

由于您使用的是模拟,因此 ID 也不会更改,但鉴于您的代码,您永远不必显式使用任何 ID。

您已经拥有的模拟就足够了,因为您无需从所述上下文中检索刚刚添加到上下文中的模型即可使用它。请记住这一点,既没有必要模拟 SaveChanges 的结果,也没有必要模拟 Count 之类的东西。

关于c# - 模拟 DbContext - 无法插入新对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28963153/

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