title: C# unit test for POST method that uses DB context with inMemoryDb
body: <p>Im using a InMemoryDatabase
  for doing some Post 's and Gets for my react app. I just started writing unit tests but one particulat one(Post_Id_WorkEntry_shouldReturn_Ok) is giving me a hard time because I get thrown an error of this type: <code>The instance of entity type ' Project ' cannot be tracked because another instance with the same key value for {' Id '} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using ' DbContextOptionsBuilder.EnableSensitiveDataLogging ' to see the conflicting key values.</code></p>
  <p>My controller:</p>
  <pre><code>    namespace Timelogger.Api.Controllers
  {
      [Route(&quot;api/[controller]&quot;)]
      public class ProjectsController : Controller
      {
          private readonly ApiContext _context;
  
          public ProjectsController(ApiContext context)
          {
              _context = context;
  
          }
  
          [HttpGet]
          [Route(&quot;HelloWorld&quot;)]
          public string HelloWorld()
          {
              return &quot;Hello Back!&quot;;
          }
  
  
          // GET api/projects
          [HttpGet]
          public IActionResult Get() //async
          {
              return Ok(_context.Projects.Include(x =&gt; x.WorkEntries));
      
          }
  
          [HttpPost]
          public async Task&lt;IActionResult&gt; Post([FromBody] Project prj)
          {
              if (ModelState.IsValid)
              {
                  try
                  {
                      Project newProject = new Project(prj.Name, prj.StartDate, prj.EndDate);
                      switch(newProject.ValidateProject())
                      {
                          case ProjectStatus.INVALID_DATE:
                              return BadRequest(&quot;Invalid dates&quot;);
  
                          case ProjectStatus.SUCCES:
                              _context.Projects.Add(newProject);
                              await _context.SaveChangesAsync();
                              return Ok(&quot;Added new project with ID=&quot; + prj.Id);
                      }
  
                  }
                  catch (Exception e)
                  {
                      return BadRequest(e.Message);
                  }
              }
              return BadRequest(&quot;Invalid json format&quot;);
          }
  
          //[HttpPut(&quot;{id}&quot;)]
          [HttpPost]
          [Route(&quot;{Id:int}/WorkEntry&quot;)]
          public async Task&lt;IActionResult&gt; Post(int id, [FromBody] WorkEntry workEntry)
          {
              if (ModelState.IsValid)
              {
                  try
                  {
                      Console.Write(&quot;WorkEntry====: &quot; + workEntry.ToString());
                      var updatedProject = _context.Projects.AsNoTracking().Include(x =&gt; x.WorkEntries).FirstOrDefault(x =&gt; x.Id == id);
                      switch (updatedProject.ValdidateAndMergeWorkEntry(workEntry))
                      {
                          case ValidStatus.SUCCES_NEW_WORKENTRY_ADDED:
                              Console.WriteLine(&quot;SUCCES_NEW_WORKENTRY_ADDED&quot;);
                              _context.Projects.Update(updatedProject);
                              await _context.SaveChangesAsync();
                              return Ok(&quot;Work entry added for project with ID=&quot; + updatedProject.Id);
  
                          case ValidStatus.SUCCES_HOURS_MERGED:
                              Console.WriteLine(&quot;SUCCES_HOURS_MERGED&quot;);
                              _context.Projects.Update(updatedProject);
                              await _context.SaveChangesAsync();
                              return Ok(&quot;Work entry merged for project with ID=&quot; + updatedProject.Id);
  
                          case ValidStatus.INVALID_HOURS_ALREADY_BOOKED:
                              Console.WriteLine(&quot;ERROR_HOURS_ALREADY_BOOKED&quot;);
                              return BadRequest(&quot;Hours are already over the legal meeting&quot;);
  
                          case ValidStatus.INVALID_DAY:
                              Console.WriteLine(&quot;INVALID_DAY&quot;);
                              return BadRequest(&quot;Day is not valid&quot;);
  
                          case ValidStatus.INVALID_HOURS:
                              Console.WriteLine(&quot;INVALID_HOURS&quot;);
                              return BadRequest(&quot;Hours are not valid&quot;);
                      }
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine(e.Message);
                      return BadRequest(e.Message);
                  }
              }
              return BadRequest(&quot;Invalid json format&quot;);
          }
  
      }
  }
  </code></pre>
  <p>And this is are my UT</p>
  <pre><code>    namespace Timelogger.Api.Tests
      {
      public class ProjectsControllerTests
      {
          ProjectsSeedDataFixture psdf = null;
  
          [SetUp]
          public void Init()
          {
              psdf = new ProjectsSeedDataFixture();
          }
  
          [TearDown]
          public void CleanUp()
          {
              psdf.ProjectsContext.Database.EnsureDeleted();
          }
  
          [Test]
          public void HelloWorld_ShouldReply_HelloBack()
          {
              //arrange
              ProjectsController sut = new ProjectsController(psdf.ProjectsContext);
  
              //act
              var actual = sut.HelloWorld();
  
              //assert
              Assert.AreEqual(&quot;Hello Back!&quot;, actual);
          }
  
          [Test]
          public void Get_shouldReturn_Ok()
          {
              //arrange
              ProjectsController sut = new ProjectsController(psdf.ProjectsContext);
              var testProject1 = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2019, 12, 1), new System.DateTime(2020, 12, 10));
              Stubs.PopulateWorkEntries(testProject1);
              psdf.ProjectsContext.Projects.Add(testProject1);
              psdf.ProjectsContext.SaveChanges();
  
              //act
              var actual = sut.Get();
              var okResult = actual as OkObjectResult;
  
              //assert
              Assert.IsNotNull(okResult);
              Assert.AreEqual(200, okResult.StatusCode);
          }
  
          [Test]
          public void Post_shouldReturn_Ok()
          {
              //arrange
              ProjectsController sut = new ProjectsController(psdf.ProjectsContext);
              var testProject1 = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2019, 12, 1), new System.DateTime(2020, 12, 10));
              Stubs.PopulateWorkEntries(testProject1);
  
              //act
              var actual = sut.Post(testProject1);
              var okResult = actual.Result as OkObjectResult;
  
              //assert
              Assert.IsNotNull(okResult);
              Assert.AreEqual(200, okResult.StatusCode);
              //Assert.AreEqual(&quot;Added new project with ID=1&quot;, okResult.Value);
   
          }
  
          [Test]
          public void Post_shouldReturn_BadRequest()
          {
              //arrange
              ProjectsController sut = new ProjectsController(psdf.ProjectsContext);
              var testProject1 = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2020, 12, 10), new System.DateTime(2019, 12, 1));
              Stubs.PopulateWorkEntries(testProject1);
  
              //act
              var actual = sut.Post(testProject1);
              var badRequestResult = actual.Result as BadRequestObjectResult;
  
              //assert
              Assert.IsNotNull(badRequestResult);
              Assert.AreEqual(400, badRequestResult.StatusCode);
              Assert.AreEqual(&quot;Invalid dates&quot;, badRequestResult.Value);
          }
  
          [Test]
          public void Post_Id_WorkEntry_shouldReturn_Ok()
          {
              //arrange
              ProjectsController sut = new ProjectsController(psdf.ProjectsContext);
              psdf.ProjectsContext.Database.EnsureDeleted();
              var project = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2019, 12, 1), new System.DateTime(2020, 12, 10));
              psdf.ProjectsContext.Projects.Add(project);
              psdf.ProjectsContext.SaveChanges();
              WorkEntry workEntry = new WorkEntry { id = project.WorkEntries.Count + 1, Day = new System.DateTime(2019, 12, 1), Hours = 3 };
  
              //act
              var actual = sut.Post(1 , workEntry);
              var okResult = actual.Result as OkObjectResult;
  
              //assert
              Assert.IsNotNull(okResult);
              Assert.AreEqual(200, okResult.StatusCode);
          }
      }
  } 
  </code></pre>
  <p>Any idea how I can make the post testable? It's because the context from the post is different then the one from UT ? is there a possibility to mock it ?</p>
  <p>Update:</p>
  <p>This is how my test class looks right now</p>
  <pre><code>    using Timelogger.Api.Controllers;
  using NUnit.Framework;
  using System;
  using Microsoft.AspNetCore.Mvc;
  using Timelogger.Entities;
  using Microsoft.EntityFrameworkCore;
  using Microsoft.Extensions.DependencyInjection;
  
  namespace Timelogger.Api.Tests
  {
      [TestFixture]
      public class ProjectsControllerTests
      {
          private static DbContextOptions&lt;ApiContext&gt; CreateNewContextOptions()
          {
              // Create a fresh service provider, and therefore a fresh 
              // InMemory database instance.
              var serviceProvider = new ServiceCollection()
                  .AddEntityFrameworkInMemoryDatabase()
                  .BuildServiceProvider();
  
              // Create a new options instance telling the context to use an
              // InMemory database and the new service provider.
              var builder = new DbContextOptionsBuilder&lt;ApiContext&gt;().UseInMemoryDatabase(&quot;data&quot;).UseInternalServiceProvider(serviceProvider);
              
              return builder.Options;
          }
  
          [Test]
          public void HelloWorld_ShouldReply_HelloBack()
          {
              using (var context = new ApiContext(CreateNewContextOptions()))
              {
                  //arrange
                  ProjectsController sut = new ProjectsController(context);
  
                  //act
                  var actual = sut.HelloWorld();
  
                  //assert
                  Assert.AreEqual(&quot;Hello Back!&quot;, actual);
              };
          }
  
          [Test]
          public void Get_shouldReturn_Ok()
          {
              using (var context = new ApiContext(CreateNewContextOptions()))
              {
                  //arrange
                  ProjectsController sut = new ProjectsController(context);
                  var testProject1 = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2019, 12, 1), new System.DateTime(2020, 12, 10));
                  Stubs.PopulateWorkEntries(testProject1);
                  context.Projects.Add(testProject1);
                  context.SaveChanges();
  
                  //act
                  var actual = sut.Get();
                  var okResult = actual as OkObjectResult;
  
                  //assert
                  Assert.IsNotNull(okResult);
                  Assert.AreEqual(200, okResult.StatusCode);
              };
          }
  
          [Test]
          public void Post_shouldReturn_Ok()
          {
              using(var context = new ApiContext(CreateNewContextOptions()))
              {
                  //arrange
                  ProjectsController sut = new ProjectsController(context);
                  var testProject1 = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2019, 12, 1), new System.DateTime(2020, 12, 10));
                  Stubs.PopulateWorkEntries(testProject1);
  
                  //act
                  var actual = sut.Post(testProject1);
                  var okResult = actual.Result as OkObjectResult;
  
                  //assert
                  Assert.IsNotNull(okResult);
                  Assert.AreEqual(200, okResult.StatusCode);
                  Assert.AreEqual(&quot;Added new project with ID=1&quot;, okResult.Value);
              };
   
          }
  
          [Test]
          public void Post_shouldReturn_BadRequest()
          {
              using (var context = new ApiContext(CreateNewContextOptions()))
              {
                  //arrange
                  ProjectsController sut = new ProjectsController(context);
                  var testProject1 = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2020, 12, 10), new System.DateTime(2019, 12, 1));
                  Stubs.PopulateWorkEntries(testProject1);
  
                  //act
                  var actual = sut.Post(testProject1);
                  var badRequestResult = actual.Result as BadRequestObjectResult;
  
                  //assert
                  Assert.IsNotNull(badRequestResult);
                  Assert.AreEqual(400, badRequestResult.StatusCode);
                  Assert.AreEqual(&quot;Invalid dates&quot;, badRequestResult.Value);
              };
          }
  
          [Test]
          public void PostIdWorkEntry_shouldReturn_Ok()
          {
              using (var context = new ApiContext(CreateNewContextOptions()))
              {
                  //arrange
                  ProjectsController sut = new ProjectsController(context);
                  var project = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2019, 12, 1), new System.DateTime(2020, 12, 10));
                  context.Projects.Add(project);
                  context.SaveChanges();
                  WorkEntry workEntry = new WorkEntry(new System.DateTime(2019, 12, 3), 3 );
  
                  //act
                  var actual = sut.Post(project.Id, workEntry);
                  var okResult = actual.Result as OkObjectResult;
  
                  //assert
                  Assert.IsNotNull(okResult);
                  Assert.AreEqual(200, okResult.StatusCode);
              };
          }
  
          [Test]
          public void PostIdWorkEntry_shouldReturn_BadRequestInvalidHoursSurpassed()
          {
              using (var context = new ApiContext(CreateNewContextOptions()))
              {
                  //arrange
                  ProjectsController sut = new ProjectsController(context);
                  var project = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2019, 12, 1), new System.DateTime(2020, 12, 10));
                  WorkEntry workEntry1 = new WorkEntry { id = project.WorkEntries.Count + 1, Day = new System.DateTime(2019, 12, 1), Hours = 7 };
                  project.WorkEntries.Add(workEntry1);
                  context.Projects.Add(project);
                  context.SaveChanges();
                  WorkEntry workEntry2 = new WorkEntry { id = project.WorkEntries.Count + 1, Day = new System.DateTime(2019, 12, 1), Hours = 2 };
  
                  //act
                  var actual = sut.Post(project.Id, workEntry2);
                  var badRequestResult = actual.Result as BadRequestObjectResult;
  
                  //assert
                  Assert.IsNotNull(badRequestResult);
                  Assert.AreEqual(400, badRequestResult.StatusCode);
                  Assert.AreEqual(&quot;Hours are over the legal point&quot;, badRequestResult.Value);
              };
          }
  
  
          [Test]
          public  void PostIdWorkEntry_shouldReturn_BadRequestInvalidDay()
          {
              using (var context = new ApiContext(CreateNewContextOptions()))
              {
                  //arrange
                  ProjectsController sut = new ProjectsController(context);
                  var project = new Project(&quot;e-conomic Interview&quot;, new System.DateTime(2019, 12, 1), new System.DateTime(2020, 12, 10));
                  context.Projects.Add(project);
                  context.SaveChanges();
                  WorkEntry workEntry = new WorkEntry { id = project.WorkEntries.Count + 1, Day = new System.DateTime(2020, 12, 11), Hours = 2 };
  
                  //act
                  var actual = sut.Post(project.Id, workEntry);
                  var badRequestResult = actual.Result as BadRequestObjectResult;
  
                  //assert
                  Assert.IsNotNull(badRequestResult);
                  Assert.AreEqual(400, badRequestResult.StatusCode);
                  Assert.AreEqual(&quot;Day is not valid&quot;, badRequestResult.Value);
              };
          }
  
  
      }
  } 
  </code></pre>