I am unit testing an application I made with an in-memory database using Entity Framework Core but I am running into a problem with one of my functions. I have so far tested getting a game by Id (it works), adding a game to the collection (it works too) and updating a game in the collection (it doesn't work).
The function code:
[TestMethod()]
public async Task UpdateGameAsyncTest()
{
//Arrange
await CreateDb();
GameDto gameDto = new GameDto()
{
Id = 2,
Team1 = "PSG",
Team2 = "AZ",
Date = DateTime.UtcNow
};
//Act
var id = await _gameService2.UpdateGameAsync(gameDto);
var game = await _gameService2.GetGameAsync(id);
//Assert
Assert.AreEqual("AZ", game.Team1);
}
UpdateGameAsync() in my service layer:
public async Task<int> UpdateGameAsync(GameDto game)
{
var gameEntity = game.ToEntity();
return await _gameRepository.UpdateGameAsync(gameEntity);
}
UpdateGameAsync() in my repository layer:
public async Task<int> UpdateGameAsync(Game game)
{
if (game.Result != null)
{
if (game.Result.Length == 3 && game.Result.Substring(1, 1) == "-")
{
game.typeResult = await CheckTypeResult(game.Result);
}
}
_dbContext.Games.Update(game);
return await AutoSaveChangesAsync();
}
CreateDb():
public async Task CreateDb()
{
var options = new DbContextOptionsBuilder<StrikeNetDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.EnableSensitiveDataLogging()
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
.Options;
var dbContext = new StrikeNetDbContext(options);
if (await dbContext.Games.CountAsync() <= 0)
{
Game g1 = new Game()
{
Id = 1,
Team1 = "FCB",
Team2 = "BVB",
Date = DateTime.UtcNow
};
Game g2 = new Game()
{
Id = 2,
Team1 = "PSG",
Team2 = "PSV",
Date = DateTime.UtcNow
};
Game g3 = new Game()
{
Id = 3,
Team1 = "Ajax",
Team2 = "Feyenoord",
Date = DateTime.UtcNow
};
dbContext.Games.Add(g1);
dbContext.Games.Add(g2);
dbContext.Games.Add(g3);
await dbContext.SaveChangesAsync();
}
var gameRepository = new GameRepository(dbContext);
_gameService2 = new GameService(gameRepository);
}
When running the test I am running into the error: "The instance of entity type 'Game' cannot be tracked because another instance with the key value '{Id: 2}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached."
For comparing purposes, here is the adding function that DOES work:
[TestMethod()]
public async Task AddGameAsyncTest()
{
//Arrange
await CreateDb();
GameDto game = new GameDto()
{
Team1 = "Juve",
Team2 = "Real",
Date = DateTime.UtcNow
};
//Act
var id = await _gameService2.AddGameAsync(game);
var expected = await _gameService2.GetGameAsync(id);
//Assert
Assert.AreEqual("Juve", expected.Team1);
}
I have tried several things that answers to similar questions suggested but none of them work for me. I do have my repository en service scoped in Startup.cs, and detaching the entities in the createdb() function als doesn't seem to work. Does anyone have any other idea?
UpdateGameAsync. That's where it's happening. - Gert Arnold