1

I am currently implementing a Database collection/fixture for my unit tests, as documented on this question here:

xUnit.net - run code once before and after ALL tests

However, instead of using an InMemory Database, I'm using SQLite as InMemory currently has a bug in .Net Core 2.1 which doesn't do a sequence check when using a byte array type

Which leads me to my current predicament, namely that the byte array when you set up a database fixture doesn't get pulled through to the unit test when the context is pulled from the Database Fixture and into the unit test, which is causing concurrency errors when I try to run the tests.

As an example:

Fist set the DatabaseFixture class like so:

public class DatabaseFixture : IDisposable
{
    public DatabaseFixture()
    {
        var connectionStringbuilder = new SqliteConnectionStringBuilder{DataSource = ":memory:", Cache = SqliteCacheMode.Shared};
        var connection = new SqliteConnection(connectionStringbuilder.ToString());

        options = new DbContextOptionsBuilder<CRMContext>()
            .UseSqlite(connection)
            .EnableSensitiveDataLogging()
            .Options;

        using (var context = new CRMContext(options))
        {
            context.Database.OpenConnection();
            context.Database.EnsureCreated();                              
            context.Persons.AddRange(persons);
            context.SaveChanges();
        } 


    }
    public DbContextOptions<CRMContext> options { get; set; }

    public void Dispose()
    {
        using (var context = new CRMContext(options))
        {
            context.Database.CloseConnection();

            context.Dispose();
        }
    }
    private IQueryable<Person> persons = new List<Person>()
        {
            new Person
            {
                Id = 1, 
                Forename = "Test",
                Surname = "User",
                RowVersion = new byte[0]
            },
            new Person
            {
                Id = 2, 
                Forename = "Another",
                Surname = "Test",
                RowVersion = new byte[0]
            }
        }.AsQueryable();
}

Setup your empty DatabaseCollection class as per the first link:

 [CollectionDefinition("Database collection")]
public class DatabaseCollection : ICollectionFixture<DatabaseFixture>
{
}

Then set up your unit test to use this Database Fixture:

[Collection("Database collection")]
 public class PersonTests : BaseTests
{
    private readonly DatabaseFixture _fixture;

    public PersonTests(DatabaseFixture fixture)
    {
        _fixture = fixture;
    }
    [Fact]
    public void SaveAndReturnEntityAsync_SaveNewPerson_ReturnsTrue()
    {
            {

        using (var context = new Context(_fixture.options))
        {
            var existingperson = new Person
            {
                Id = 2,
                Forename = "Edit",
                Surname = "Test",
                RowVersion = new byte[0]
            };
            var mapperConfig = new MapperConfiguration(cfg => { cfg.AddProfile(new InitializeAutomapperProfile()); });

            var AlertAcknowledgeService = GenerateService(context);

            //Act
            //var result = _Person.SaveAndReturnEntityAsync(mappedPersonAlertAcknowledge);
            //Assert
            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.True(result.IsCompletedSuccessfully);
            Assert.Equal("The data is saved successfully", result.Result.SuccessMessage);
        }
    }

Now when I debug this, it hits the fixture correctly, and you can when you expand the Results view, the RowVersion variable is assigned correctly:

Correct Row Version value

However, when the data is passed into the unit test, the row version gets set to null:

Row Version set to null

Any help on this would be greatly appreciated!

Federico Navarrete
  • 3,069
  • 5
  • 41
  • 76
  • Looks like you might have a race condition as you're calling an async method without awaiting it and then asserting the task result is complete right after. (Not sure if this is part of your problem). I recommend making the test async and awaiting the result call. – Kieran Devlin Feb 11 '21 at 08:55

0 Answers0