I am using autofixture, nsubstitude and fluent assertions in my unit tests.
This is my main code:
public async Task<ServiceResponse<PlanInventoryDto>> Update(PlanInventoryDto planInventoryDto)
{
planInventoryDto.ThrowIfNull(nameof(planInventoryDto));
if (planInventoryDto == null)
{
return serviceResponseHelper.SetError<PlanInventoryDto>(null, localize["InvalidModel"], StatusCodes.Status400BadRequest, true);
}
var partProdArea = repository.GetQueryable().FirstOrDefault(predicate: q => q.Id == planInventoryDto.Id);
if (partProdArea != null)
{
var mappingResult = mapper.Map(planInventoryDto, partProdArea);
await repository.UpdateAsync(mappingResult).ConfigureAwait(false);
var result = repository.GetFirstOrDefault(predicate: p => p.Id == planInventoryDto.Id);
var dto = mapper.Map<PlanInventory, PlanInventoryDto>(result);
return serviceResponseHelper.SetSuccess(dto);
}
return serviceResponseHelper.SetError<PlanInventoryDto>(null, localize["ModelIsNotFound"], StatusCodes.Status400BadRequest, true);
}
And this is my unit test:
[Fact]
[Trait("Operation", "Update")]
[Trait("Category", "PlanInventory")]
public async Task PlanInventoryService_Update_ReturnsSuccessResponse()
{
// Arrange
var planInventoryDto = _fixture.Create<PlanInventoryDto>();
var planInventory = _fixture.Build<Domain.PlanProcess.PlanInventory>()
.With(p => p.Id, planInventoryDto.Id)
.Create();
var updatedPlanInventory = _fixture.Create<Domain.PlanProcess.PlanInventory>();
var updatedDto = _fixture.Create<PlanInventoryDto>();
_repository.GetFirstOrDefault(Arg.Any<Expression<Func<Domain.PlanProcess.PlanInventory, bool>>>(),
Arg.Any<Func<IQueryable<Domain.PlanProcess.PlanInventory>, IOrderedQueryable<Domain.PlanProcess.PlanInventory>>>(),
Arg.Any<Func<IQueryable<Domain.PlanProcess.PlanInventory>, IIncludableQueryable<Domain.PlanProcess.PlanInventory, object>>>())
.Returns(planInventory);
_repository.GetFirstOrDefault(Arg.Any<Expression<Func<Domain.PlanProcess.PlanInventory, bool>>>(),
Arg.Any<Func<IQueryable<Domain.PlanProcess.PlanInventory>, IOrderedQueryable<Domain.PlanProcess.PlanInventory>>>(),
Arg.Any<Func<IQueryable<Domain.PlanProcess.PlanInventory>, IIncludableQueryable<Domain.PlanProcess.PlanInventory, object>>>())
.Returns(updatedPlanInventory);
_mapper.Map(Arg.Any<PlanInventoryDto>(), Arg.Any<Domain.PlanProcess.PlanInventory>())
.Returns(updatedPlanInventory);
_repository.UpdateAsync(Arg.Any<Domain.PlanProcess.PlanInventory>())
.Returns(Task.FromResult(updatedPlanInventory));
_mapper.Map<Domain.PlanProcess.PlanInventory, PlanInventoryDto>(updatedPlanInventory)
.Returns(updatedDto);
// Act
var result = await _planInventoryService.Update(planInventoryDto);
// Assert
_serviceResponseHelper.Received(1).SetSuccess(Arg.Any<PlanInventoryDto>());
}
Result is getting null beacause partProdArea variable getting null from main code. I could not figure it out no matter what i have tried. Is there a different writing way of FirstOrDefault that has predicate, i could not figure it out a little help would be very helpful.
As I said in a comment, in your production code, you have: repository.GetQueryable().FirstOrDefault()
. However, you are not mocking the GetQueryable()
method of your _repository
!
You could create a variable representing the IQueryable
that is returned from that method, containing the planInventory
, and setup your _repository
to return it. This way, you don't need to mock explicitly the .FirstOrDefault
method:
IEnumerable<Order> inventories = new List<Domain.PlanProcess.PlanInventory> { planInventory }; // Create a list with a single element, the planInventory
IQueryable<Order> inventoriesQuery = inventories.AsQueryable(); // Transform the list in a IQueryable, since that is the type returned by the `GetQueryable()`
_repository.GetQueryable().Returns(inventoriesQuery); // Tell the mock to return the IQueryable when GetQueryable() is called