0

I do not have much experience with testing in .NET. I ran into an issue that I do not understand how to solve. Please advise where I can read about it.

I have a backend code that works with a simple database. I already created a frontend for it and everything works fine. But I wanted to add unit testing. I created a test project (VS template, xUnit) and added dependency Microsoft.EntityFrameworkCore.InMemory.

All my tests work, except a test for PUT. I receive the error: System.InvalidOperationException : The instance of entity type 'UserTask' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. I tried to use .sqlite in memory instead of .inmemory and got the same error. My understanding is that I am supposed to test how _context.Entry(task).State = EntityState.Modified; await _context.SaveChangesAsync(); works and for some reason, I cannot test it because it doesn't detach the entity that I am replacing. ChatGPT suggested detaching it manually but then what am I testing there - it doesn't look to me like a valid test. Also, I found that I can use Context.Entry(entity).Reload(), but because I have a problem inside of the line var postResult = await _controller.PutTask(1,newTask), I don't think I can apply it.

Please direct me where I can find information about how to test this method.

In my controller in the main project:

    // PUT: api/Task/5
 [HttpPut("{id}")]
 public async Task<IActionResult> PutTask(int id, [FromBody] UserTask task)
 {
     if (id != task.Id ||
         !Enum.IsDefined(typeof(StatusEnum), task.Status) ||
         !Enum.IsDefined(typeof(PriorityEnum), task.Priority))
     { return BadRequest(); }

     _context.Entry(task).State = EntityState.Modified;

     try
     {
         await _context.SaveChangesAsync();
     }
     catch (DbUpdateConcurrencyException)
     {
         if (!TaskExists(id))
         {
             return NotFound();
         }
         else
         {
             throw;
         }
     }

     return NoContent();
 }

In my test file in the test project:

    public class TaskControllerTests : IDisposable
     {
         private readonly UserTasksContext _context;
         private readonly TaskController _controller;
    
         public TaskControllerTests()
         {
             var options = new DbContextOptionsBuilder<UserTasksContext>()
                 .UseInMemoryDatabase("TaskManagerTestDb")
                 .Options;
    
             _context = new UserTasksContext(options);
             _controller = new TaskController(_context);
    
             SeedDatabase();
         }
    
         private void SeedDatabase()
         {
             _context.UserTasks.AddRange(
                 new UserTask { Id = 1, Title = "Task 1", DueDate = DateTime.Now, Priority = "High", Status = "Pending" },
                 new UserTask { Id = 2, Title = "Task 2", DueDate = DateTime.Now, Priority = "Low", Status = "Completed" }
             );
             _context.SaveChanges();
         }
    
         public void Dispose()
         {
             _context.Database.EnsureDeleted();
             _context.Dispose();
         }
           [Fact]
  public async Task PutTask_EditsNew_ValidTask()
  {
      // Arrange
      var newTask = new UserTask {Id=1, Title = "New Task", DueDate = DateTime.Now.AddDays(3), Priority = "VeryHigh", Status = "InProgress" };

      // Act
      var postResult = await _controller.PutTask(1,newTask);
      var getResult = await _controller.GetTasks();

      // Assert
      var actionResult = Assert.IsType<ActionResult<IEnumerable<UserTask>>>(getResult);
      var tasks = Assert.IsAssignableFrom<IEnumerable<UserTask>>(actionResult.Value);
      Assert.Equal(2, tasks.Count());
      Assert.NotNull(tasks?.LastOrDefault());
      Assert.Equal("New Task", tasks?.FirstOrDefault()?.Title);
      Assert.Equal("InProgress", tasks?.FirstOrDefault()?.Status);
  }
}

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.