Search code examples
c#.net-corenunit-3.0

NUnit Test With InMemoryDatabase Return Count 0


I'm implementing some NUnit tests with InMemoryDatabase.

When I have test to save in database it works, that test has been passed, but if I want in separate test method to return list as result. That list is empty, it has been returned 0 as count, instead of 300.

Test method GetPaymentCalendar_WithFactoryIdRequest_ReturnCount is failing.

Can someone give me a tip, what I'm doing wrong ?

public class PaymentCalendarRequestServiceTests
{
    private IPaymentCalendarService _paymentCalendarService;
    private ApplicationDbContext _context;
    private IUnitOfWork _unitOfWork;

    [SetUp]
    public void Init()
    {
        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseInMemoryDatabase("TestDb")
            .Options;
        var currentUserServiceMock = new Mock<ICurrentUserService>(MockBehavior.Strict);
        currentUserServiceMock.Setup(_ => _.UserId).Returns(Guid.NewGuid().ToString);
        var dateTimeServiceMock = new Mock<IDateTimeService>(MockBehavior.Strict);
        dateTimeServiceMock.Setup(_ => _.Now).Returns(DateTime.Now);
        _context = new ApplicationDbContext(options, currentUserServiceMock.Object, dateTimeServiceMock.Object);
        _unitOfWork = new UnitOfWork(_context, dateTimeServiceMock.Object, currentUserServiceMock.Object);

        _paymentCalendarService = new PaymentCalendarService(_unitOfWork);
    }

    [Test]
    public void CreatePaymentCalendar_WithValidPaymentCalendarCreateRequest_ReturnSuccess()
    {
        var request = new List<PaymentCalendarCreateRequest>();
        for (int i = 0; i < 25 * 12; i++)
        {
            request.Add(
                new PaymentCalendarCreateRequest
                {
                    Month = DateTime.Now.AddMonths(i).Month,
                    Year = DateTime.Now.AddMonths(i).Year,
                    IsClosed = false,
                    FactoryId = "25aa09a6-006c-4571-ae45-68b697a54fec"
                }
            );
        }
        var result = _paymentCalendarService.CreatePaymentCalendar(request).Result;
        Assert.IsTrue(result.Succeeded);
    }

    [Test]
    public void GetPaymentCalendar_WithFactoryIdRequest_ReturnCount()
    {
        var factoryId = "25aa09a6-006c-4571-ae45-68b697a54fec";
        var response = _paymentCalendarService.GetPaymentCalendar(factoryId).Result;
        Assert.AreEqual(25*12,response.Count);
    }
}

Solution

  • As the already given answer establishes, your setup is run individually for each test. There is no carried-over state. But what I want to address in this answer is that there shouldn't be carry-over, because you're still looking for a way to achieve carry-over in response to the previously given answer.

    Setting up the data when you want to write a data-retrieval test should be part of that test. The data should not be set up using some other test, because this creates a dependency between tests and the order they are executed in, and you want to very much avoid that. Each test should be self-contained and you should be able to run them (and have them make sense) individually.

    Even for integration tests, a test should set up its own data. Ideally, it also cleans up after itself, but that can arguably be skipped if the database is discarded after the test suite has run (and the existence of uncleaned data does not interfere with other tests).

    [Test]
    public void GetPaymentCalendar_WithFactoryIdRequest_ReturnCount()
    {
        // Set the data you want to be available in the db here
    
        var factoryId = "25aa09a6-006c-4571-ae45-68b697a54fec";
        var response = _paymentCalendarService.GetPaymentCalendar(factoryId).Result;
        Assert.AreEqual(25*12,response.Count);
    }
    

    In other words, something like:

    [Test]
    public void GetPaymentCalendar_WithFactoryIdRequest_ReturnCount()
    {
        var factoryId = "25aa09a6-006c-4571-ae45-68b697a54fec";
    
        _context.Payments.Add(new Payment() { ... });
        _context.Payments.Add(new Payment() { ... });
        _context.Payments.Add(new Payment() { ... });
        _context.SaveChanges();
    
        var response = _paymentCalendarService.GetPaymentCalendar(factoryId).Result;
        
        Assert.AreEqual(3,response.Count);
    }
    

    I don't know your data model so there are some obvious gaps in the code here. The main purpose is to highlight what should be happening here, you'll have to fill in the details yourself.

    Feel free to add helper/private methods to abstract away the bulky arrange logic so you can keep the test body mostly focused on what is being tested, as opposed to how it is being arranged.