See here for my simple test case:
https://github.com/aherrick/TestServerInMemoryEFCoreSelenium
I am using XUnit + Selenium to run tests. My scenario is as follows:
The part where this is failing is Step 3. The record is still the old original data from Step 1.
Is this a limitation of EF Core In Memory? Is something else at play here?
Thanks!
Test Code:
[Fact]
public void Run()
{
// add new user
var db = Server.HostWeb.Services.GetService<ApplicationDbContext>();
db.User.Add(new User()
{
Name = "Andrew"
});
db.SaveChanges();
// edit the user from the test (Home/Edit) action
Browser.Navigate().GoToUrl(Server.RootUrl);
var editBtn = By.Id("edit");
Browser.FindElement(editBtn).Click();
// just wait until ajax is done for now.
Thread.Sleep(20000);
db = Server.HostWeb.Services.GetService<ApplicationDbContext>();
// Name should be "Herrick" as my Home/Edit updates the record
var data = db.User.First();
Assert.Equal("Herrick", data.Name);
}
@aherrick It's because the same context instance is being used both for the insertion and the assertion. This means that when you query for the entity with db.User.First() you get back the already tracked instance, which still has the old name.
@ajcvickers Thanks for the response! Is this suggestion to create a new instance via scope?
Example:
var serviceScopeFactory = Server.HostWeb.Services.GetService<IServiceScopeFactory>();
db = serviceScopeFactory.CreateScope().ServiceProvider.GetService<ApplicationDbContext>();
Do this does pull the correct data.
@aherrick Really depends what you are trying to test. A no-tracking query for the assertion would also work in this case. But probably creating an explicit unit-of-work, for example using a scope, for the insert is a good idea anyway.
Most helpful comment
@aherrick Really depends what you are trying to test. A no-tracking query for the assertion would also work in this case. But probably creating an explicit unit-of-work, for example using a scope, for the insert is a good idea anyway.