I have a Generic Repository Pattern that receive the domain as Generic Type and I am creating a Unit Test for my Query Handler and using InMemoryDatabase.
The code below it's a reference for this post and I implemented it for my case.
public class ContractTypeSeedDataFixture : IDisposable
{
public Fixture _fixture = new();
public PaperclipContext PaperclipContext { get; private set; }
const string BILLS_OPERATION_TIME = "{ \"id\": 3... }";
const string TAX_OPERATION_TIME = "{ \"id\": 6... }";
const string PIX_OPERATION_TIME = "{ \"id\": 1... }";
public ContractTypeSeedDataFixture()
{
var options = new DbContextOptionsBuilder<PaperclipContext>()
.UseInMemoryDatabase(databaseName: "unitTestDatabase")
.Options;
PaperclipContext = new PaperclipContext(options);
_fixture.Behaviors.Remove(new ThrowingRecursionBehavior());
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_fixture.Register(() => _fixture.Build<List<Func<IDomainEvent>>>().Create());
_fixture.Register(() => _fixture.Build<DefaultContractNotifications>().Create());
PaperclipContext.ContractType.Add(_fixture.Build<ContractType>().With(p => p.OperationTime, BILLS_OPERATION_TIME).Create());
PaperclipContext.ContractType.Add(_fixture.Build<ContractType>().With(p => p.OperationTime, TAX_OPERATION_TIME).Create());
PaperclipContext.ContractType.Add(_fixture.Build<ContractType>().With(p => p.OperationTime, PIX_OPERATION_TIME).Create());
PaperclipContext.ContractType.Add(_fixture.Build<ContractType>().Without(p => p.OperationTime).Create());
PaperclipContext.SaveChanges();
}
public void Dispose()
{
PaperclipContext.Dispose();
}
}
This part that's fine because I put a breakpoint and returned the data that I added using the ContractTypeSeedDataFixture
.
[Fact(DisplayName = "Should return contractTypeOperationTimeViewModel ordered by id.")]
public async Task Get_OperationTime_ReturnContractTypeOperationTimeViewModel()
{
// Arrange
var t = _contractTypeSeedDataFixture.PaperclipContext.ContractType.ToList();
}
To know, the Query Handler that I want to test it's the code below. Then I get IRepository<domain.Entities.ContractType> _contractTypeRepository
in my constructor
public async Task<IOrderedEnumerable<ContractTypeOperationTimeViewModel>> Handle(GetContractTypeOperationTimeQuery request, CancellationToken cancellationToken)
{
var contractsTypeOperation = _contractTypeRepository
.List()
.AsNoTracking()
.Where(cT => cT.OperationTime != null)
.Select(cT => JsonConvert.DeserializeObject<ContractTypeOperationTimeViewModel>(cT.OperationTime))
.AsEnumerable()
OrderBy(cT => cT.Id);
return await Task.FromResult(contractsTypeOperation);
}
The test that I am creating it's below
public class GetContractTypeOperationTimeQueryHandlerTests : IClassFixture<ContractTypeSeedDataFixture>
{
private readonly ContractTypeSeedDataFixture _contractTypeSeedDataFixture = new();
private readonly IRepository<Domain.ContractType> _contractTypeRepository;
public GetContractTypeOperationTimeQueryHandlerTests(ContractTypeSeedDataFixture contractTypeSeedDataFixture)
{
_contractTypeSeedDataFixture = contractTypeSeedDataFixture;
}
[Fact(DisplayName = "Should return contractTypeOperationTimeViewModel ordered by id.")]
public async Task Get_OperationTime_ReturnContractTypeOperationTimeViewModel()
{
// Arrange
// Act
var getContractTypeOperationTimeQuery = new GetContractTypeOperationTimeQuery();
var getContractTypeOperationTimeQueryHandler = new GetContractTypeOperationTimeQueryHandler(_contractTypeRepository);
var contractTypeOperationTimeViewModel = await getContractTypeOperationTimeQueryHandler.Handle(getContractTypeOperationTimeQuery, new CancellationToken());
// Assert
Assert.Equal(1, contractTypeOperationTimeViewModel.First().Id);
//contractTypeOperationTimeViewModel.Should().BeInAscendingOrder(compare => compare.Id);
}
}
But the problem is that when I run the test, in the Query Handler, the _contractTypeRepository
it's null, but I think, why it's null if I am using some seed fixture to generate my data?
I tried to send the IRepository in the constructor.
I created a specific repository and it's worked but here we use generic repository pattern.
You need to initialize your repository variable:
_contractTypeRepository = new Repository<Domain.ContractType>(_contractTypeSeedDataFixture.PaperclipContext);
Whole class example:
public class GetContractTypeOperationTimeQueryHandlerTests : IClassFixture<ContractTypeSeedDataFixture>
{
private readonly ContractTypeSeedDataFixture _contractTypeSeedDataFixture = new();
private readonly IRepository<Domain.ContractType> _contractTypeRepository = new Repository<Domain.ContractType>(_contractTypeSeedDataFixture.PaperclipContext);
public GetContractTypeOperationTimeQueryHandlerTests(ContractTypeSeedDataFixture contractTypeSeedDataFixture)
{
_contractTypeSeedDataFixture = contractTypeSeedDataFixture;
}
[Fact(DisplayName = "Should return contractTypeOperationTimeViewModel ordered by id.")]
public async Task Get_OperationTime_ReturnContractTypeOperationTimeViewModel()
{
// Arrange
// Act
var getContractTypeOperationTimeQuery = new GetContractTypeOperationTimeQuery();
var getContractTypeOperationTimeQueryHandler = new GetContractTypeOperationTimeQueryHandler(_contractTypeRepository);
var contractTypeOperationTimeViewModel = await getContractTypeOperationTimeQueryHandler.Handle(getContractTypeOperationTimeQuery, new CancellationToken());
// Assert
Assert.Equal(1, contractTypeOperationTimeViewModel.First().Id);
//contractTypeOperationTimeViewModel.Should().BeInAscendingOrder(compare => compare.Id);
}
}