External service mock for method doesn't work - c#

We have some external service method to call from our code, looks. like
AssignOrderReserveCommandResponseDto response = await _supplyReservesClient.AssignOrderReserve(
masterReserveId,
inboundReserveId,
deliveryDate,
orderInfos,
cancellationToken)
Mock for this method looks like:
public static readonly ISupplyReservesClient SupplyReservesClient = Substitute.For<ISupplyReservesClient>();
public static AssignOrderReserveCommandResponseDto assignOrderReserveCommandResponse;
static SupplyReservesClientMock()
{
SupplyReservesClient
.AssignOrderReserve(Arg.Any<Guid>(), Arg.Any<Guid>(),
Arg.Any<DateTimeOffset>(), Arg.Any<IReadOnlyCollection<AssignOrderInfo>>(),
Arg.Any<CancellationToken>())
.Returns(_ => assignOrderReserveCommandResponse);
}
public static void SetAssignOrderReserveCommandResponseDto(long bidId, long otherBidId)
{
Fixture fixture = new Fixture();
assignOrderReserveCommandResponse = fixture.Build<AssignOrderReserveCommandResponseDto>()
.With(x => x.OrderInfos, new List<AssignOrderReserveCommandResponseDto.OrderInfo>()
{
new(bidId, "1", DateTime.UtcNow.AddDays(3)),
new(otherBidId, "1", DateTime.UtcNow.AddDays(3))
})
.With(x => x.InboundReserveId, fixture.Create<Guid>())
.Create();
}
Mock doesn't work and method returns null when I use debug for my test or just run test
Method for mock:
public async Task<AssignOrderReserveCommandResponseDto> AssignOrderReserve(
Guid? masterReserveId,
Guid? inboundReserveId,
DateTimeOffset deliveryDate,
IReadOnlyCollection<AssignOrderInfo> orderInfos,
CancellationToken cancellationToken)
{
AssignOrderReserveCommand command = AssignOrderReserveConverter
.Convert(masterReserveId, inboundReserveId, deliveryDate, orderInfos);
AssignOrderReserveCommandResponse response = await _supplyReservesClient
.AssignOrderReserveAsync(command, cancellationToken: cancellationToken);
return AssignOrderReserveConverter.Convert(response);
}

Related

Expression> is not working as expected in mock setup xunit .net6

I try to test this method using xunit .
public async Task<IList<DraftEntity>> Handle(GetDraftsQuery request, CancellationToken cancellationToken)
{
var res = await _repository.GetAllAsync(a => a.CustomerIsin == _user.CustomerIsin);
return res.Data;
}
Here is my test code :
public async void GetDraftsQueryTest_when_customerISIN_is_same_draft_is_not_null()
{
//Arange
IList<DraftEntity> ListOutpuddata = new List<DraftEntity>() { new DraftEntity()
{
CustomerIsin=customerisin,
}
};
repo.Setup(i => i.GetAllAsync(i=>i.CustomerIsin==It.IsAny<string>())).Returns(Task.FromResult(OperationResult<IList<DraftEntity>>.Succeed(ListOutpuddata)));
}
But when I debug the code the res variable in my method is null .Why ?
Final setup
repo.Setup(i => i.GetAllAsync(It.IsAny<Expression<Func<DraftEntity, bool>>>())).Returns(Task.FromResult(OperationResult<IList<DraftEntity>>.Succeed(ListOutpuddata)));

IMediator Mock returns null when I set up it in test

Here is my code:
public sealed class BulkAddStockConditionItemCommandHandler : IRequestHandler<BulkAddStockConditionItemCommand,
UserStockConditionSetsEntity>
{
private readonly IMediator _mediator;
public BulkAddStockConditionItemCommandHandler(IMediator mediator)
{
_mediator = mediator;
}
public async Task<UserStockConditionSetsEntity> Handle(BulkAddStockConditionItemCommand request,
CancellationToken cancellationToken)
{
var conditionalRiskAgreements = new ConditionalRiskAgreementEntity(_userService.CustomerIsin);
var addRes = await _mediator.Send(new AcceptConditionalRiskAgreementCommand(), cancellationToken);
if (addRes == null) throw new Exception();
//...code removed for brevity
}
}
I inject the IMediator into my constructor and I need the addRes not be NULL in my unit test scenario, so here you can see my test scenario:
public async void BulkAddStockConditionItemCommand_when_StockConditionSet_is_null()
{
//arrange
var condition = new ConditionalRiskAgreementEntity(RandomIsin);
var mediator = new Mock<IMediator>();
mediator.Setup(i => i.Send(It.IsAny<ConditionalRiskAgreementEntity>(), It.IsAny<System.Threading.CancellationToken>())).ReturnsAsync(Task.FromResult<object>(condition));
BulkAddStockConditionItemCommand command = new BulkAddStockConditionItemCommand(data);
BulkAddStockConditionItemCommandHandler handler = new BulkAddStockConditionItemCommandHandler(mediator.Object, userservice.Object, repoacc.Object, CacheableRepository.Object);
//Act
var caughtException = await Assert.ThrowsAsync<Exception>(() => handler.Handle(command, new System.Threading.CancellationToken()));
//Assert
Assert.IsType<Exception>(caughtException);
}
I set up the IMediator as but when I run the test it returns null instead of condition variable. Why?
Based on the shown code, the subject under test uses AcceptConditionalRiskAgreementCommand
//...
var addRes = await _mediator.Send(new AcceptConditionalRiskAgreementCommand(), cancellationToken);
//...
but in the test the mocked mediator is setup to expect ConditionalRiskAgreementEntity
//...
mediator.Setup(i => i.Send(It.IsAny<ConditionalRiskAgreementEntity>(), It.IsAny<System.Threading.CancellationToken>()))
.ReturnsAsync(Task.FromResult<object>(condition));
//...
The mock will return null by default when the argument matchers do not match in the invoked member.
There is no need to return Task.FromResult<object>(condition) in ReturnsAsync since that will wrap whatever you pass in a Task
First I suggest you refactor the test to use async Task instead of async void and then update the mock to expect the actual argument types used in the subject under test.
public async Task BulkAddStockConditionItemCommand_when_StockConditionSet_is_null() {
//Arrange
var condition = new ConditionalRiskAgreementEntity(RandomIsin);
var mediator = new Mock<IMediator>();
mediator
.Setup(i => i.Send(It.IsAny<AcceptConditionalRiskAgreementCommand>(), It.IsAny<System.Threading.CancellationToken>()))
.ReturnsAsync(condition);
BulkAddStockConditionItemCommand command = new BulkAddStockConditionItemCommand(data);
BulkAddStockConditionItemCommandHandler handler = new BulkAddStockConditionItemCommandHandler(mediator.Object, userservice.Object, repoacc.Object, CacheableRepository.Object);
//Act
var caughtException = await Assert.ThrowsAsync<Exception>(() => handler.Handle(command, new System.Threading.CancellationToken()));
//Assert
Assert.IsType<Exception>(caughtException);
}

Mock GetAsync of IElasticClient. Error: Convert IGetResponse<> to GetResponse<>

everyone.
I have been trying write mock test to my IElasticClient calls, but I have problem with a error about convert. Convert IGetResponse to GetResponse.
My method of ElasicClient:
public class GetClientByIdQueryHandler : IQueryHandler<GetClientByIdQuery, Client>
{
private readonly IElasticClient _elasticClient;
private readonly IReadModel _readModel;
public GetProposalByIdQueryHandler(IElasticClient elasticClient, IReadModel readModel)
{
...
}
public async Task<Client> ExecuteQueryAsync(GetClientByIdQuery query, CancellationToken cancellationToken)
{
var readModelDescription = _readModel.GetReadModelDescription<ClientReadModel>();
var indexName = readModelDescription.IndexName.Value;
var getResponse = await _elasticClient
.GetAsync<ClientReadModel>(query.Id.Value, d => d.Index(indexName).RequestConfiguration(c => c.AllowedStatusCodes((int)HttpStatusCode.NotFound)), cancellationToken)
.ConfigureAwait(false);
return getResponse.Source;
}
}
My Mock test:
private const string _indexName = "client-document";
private ClientReadModel GetClientReadModel()
{
var response = JsonConvert.DeserializeObject<ClientReadModel>("...string json...");
return response;
}
[Fact]
public async Task GetClientByIdQueryHandler()
{
// Arrange
var mockElasticClient = new Mock<IElasticClient>();
var mockResponse = new Mock<IGetResponse<ClientReadModel>>();
mockResponse.SetupGet(r => r.Source).Returns(GetClientReadModel());
mockElasticClient
.Setup(x => x.GetAsync(
"id-d862975d-06ea-4f50-b7d3-d2b19413cb4c",
It.IsAny<Func<GetDescriptor<ClientReadModel>, IGetRequest>>(),
It.IsAny<CancellationToken>()))
.Returns(mockResponse.Object); // <== error here
...
...
}
Almost alright, but it returns a error on the line "Returns(mockResponse.Object);":
cannot convert from 'Nest.IGetResponse' to 'Nest.GetResponse
Someone have idea about resolve this problem?
Thanks!

moq method call not being verified

I have a test method that is failing on sso.verify notice the CheckUsername method has two await calls in a async method ? but because of that the sso verify never returns and thus is not verified. But the code is called. What would be the proper way to test this ?
public void Setup()
{
nav = new Mock<INavService>();
sso = new Mock<ISSOApiService>();
_vm_Successs = new ForgotPasswordViewModel(nav.Object, sso.Object);
sso.Setup(x => x.SendEmailCodeRequestAsync(It.IsAny<PasswordTokenRequest>())).ReturnsAsync(new StandardResponse() { ErrorCode = null }).Verifiable();
nav.Setup(x => x.NavigateTo<ForgotPasswordEnterCodeModel, string>(It.IsAny<string>())).Verifiable();
}
[Test]
public void CheckUserName_Success()
{
_vm_Successs.UserName = "Timmy";
var response = _vm_Successs.CheckUsername();
sso.Verify(e => e.SendEmailCodeRequest(It.IsAny<PasswordTokenRequest>()), Times.Once);
nav.Verify(mock => mock.NavigateTo<ForgotPasswordEnterCodeModel, string>(It.IsAny<string>()), Times.Once);
}
This is the checkusername method
public async Task CheckUsername()
{
PasswordTokenRequest r = new PasswordTokenRequest();
await SSOAPIService.SendEmailCodeRequestAsync(r);
await NavService.NavigateTo<ForgotPasswordEnterCodeModel, string>(UserName);
}
you should await test method therefore you need to make your test 'async Task' type
also need to setup SendEmailCodeRequestAsync with ReturnsAsync
[Test]
public async Task ShouldDeleteAzureBlobById()
{
sso.Setup(x => x.SendEmailCodeRequestAsync(It.IsAny<PasswordTokenRequest>()))
.ReturnsAsync(new StandardResponse() { ErrorCode = null })
.Verifiable();
_vm_Successs.UserName = "Timmy";
var response = await _vm_Successs.CheckUsername();
sso.Verify(e => e.SendEmailCodeRequestAsync(It.IsAny<PasswordTokenRequest>()), Times.Once);
nav.Verify(mock => mock.NavigateTo<ForgotPasswordEnterCodeModel, string>(It.IsAny<string>()), Times.Once);
}

Moq: running flows with FluentValidation

I'm using FluentValidation to validate request. If the validation fails UseCaseHandler should not be invoked. Within the UseCaseHandler I'm usign IRepository, and this is checked to see if the UseCaseHandler gets invoked.
The Request validator
public class MyValidator: AbstractValidator<Request>
{
public MyValidator()
{
RuleFor(rq=> rq)
.Cascade(CascadeMode.Continue);
RuleFor(rq=> rq)
.Must(property => property.id != default(Guid))
.WithMessage(message => $"invalid id.")
.WithName(member => nameof(member.Id));
}
}
This is the test
[Fact]
public async Task Test()
{
Mock<IUnitOfWork> uowMock = new Mock<IUnitOfWork>();
Mock<IRepository> repositoryMock = new Mock<IRepository>(MockBehavior.Strict);
Mock<IValidator<Request>> validatorMock = new Mock<IValidator<Request>>(MockBehavior.Strict);
var request = new Request
{
Id = Guid.NewGuid()
};
validatorMock
.Setup(validator => validator.Validate(request))
.Returns(new ValidationResult());
repositoryMock
.Setup(repo => repo.SaveAsync(It.IsAny<object>()))
.Returns(Task.CompletedTask);
var sut = new UseCase(uowMock.Object, repositoryMock.Object, validatorMock.Object);
Func<Task> act = () => sut.UseCaseHandler(request);
await act.Should().NotThrowAsync();
repositoryMock.Verify(repo => repo.SaveAsync(It.IsAny<object>()), Times.Once);
}
I'm looking to write a test that will check the flow.
If the validation fails the test should fail and SaveAsync should not be called.
If the validation succeeds that the test should succeed also and SaveAsync should be called one time.
What is the way to write a test ?
UPDATE
This is the use case class definition.
UseCaseHandlerProxy is a base abstract class which acts as a proxy
public class UseCase : UseCaseHandlerProxy<Request, Response>
{
private readonly IRepository _repository;
public UseCase(IUnitOfWork unitOfWork, IRepository repository, IValidator<Request> validator)
: base(unitOfWork, validator)
{
_repository = repository
}
public override async Task<Response> UseCaseHandler(Request request)
{
Order order = new Order();
order.Create();
await _repository.SaveAsync(order);
return new Response(order.Id);
}
}
This is the Request class definition
class Request
{
public Guid Id { get; set; }
}
Te response only returns the same Id
Proxy class
public abstract class UseCaseHandlerProxy<TRequest, TResponse> : IUseCaseHandler<TRequest, TResponse>
where TRequest : IRequest
where TResponse : Response
{
private IValidator<TRequest> Validator { get; }
protected internal IUnitOfWork UnitOfWork { get; }
public UseCaseHandlerProxy(IUnitOfWork unitOfWork, IValidator<TRequest> validator)
{
Validator = validator;
UnitOfWork = unitOfWork;
}
async Task<TResponse> IUseCaseHandler<TRequest, TResponse>.HandleAsync(TRequest request)
{
ValidationResult validationResult = await Validator.ValidateAsync(request);
TResponse response;
if (!validationResult.IsValid)
{
response = (TResponse)System.Activator.CreateInstance(typeof(TResponse));
validationResult.Errors.ToList().ForEach(error => response.AddError(error.PropertyName, error.ErrorMessage));
return response;
}
response = await UseCaseHandler(request);
return response;
}
public abstract Task<TResponse> UseCaseHandler(TRequest request);
}
Given the flow you want to test I would say that you are invoking the wrong member.
Cast the sut to IUseCaseHandler<TRequest, TResponse> to get access to HandleAsync which is what does the desired flow.
For example the following verifies that if no validation error that repository invokes save.
[Fact]
public async Task UseCase_Should_Save() {
//Arrange
Mock<IUnitOfWork> uowMock = new Mock<IUnitOfWork>();
Mock<IRepository> repositoryMock = new Mock<IRepository>(MockBehavior.Strict);
Mock<IValidator<Request>> validatorMock = new Mock<IValidator<Request>>(MockBehavior.Strict);
var request = new Request {
Id = Guid.NewGuid()
};
validatorMock
.Setup(validator => validator.ValidateAsync(request, It.IsAny<CancellationToken>()))
.ReturnsAsync(new ValidationResult());
repositoryMock
.Setup(repo => repo.SaveAsync(It.IsAny<object>()))
.Returns(Task.FromResult((object)null));
var sut = new UseCase(uowMock.Object, repositoryMock.Object, validatorMock.Object) as IUseCaseHandler<Request, Response>;
//Act
Func<Task> act = () => sut.HandleAsync(request);
//Assert
await act.Should().NotThrowAsync();
repositoryMock.Verify(repo => repo.SaveAsync(It.IsAny<object>()), Times.Once);
}
The following verifies that if there are errors, then the repository does not save
[Fact]
public async Task UseCase_Should_Not_Save() {
//Arrange
var uowMock = new Mock<IUnitOfWork>();
var repositoryMock = Mock.Of<IRepository>();
var validatorMock = new Mock<IValidator<Request>>(MockBehavior.Strict);
var request = new Request {
Id = Guid.NewGuid()
};
var result = new ValidationResult();
result.Errors.Add(new ValidationFailure("SomeProperty", "SomeError"));
validatorMock
.Setup(validator => validator.ValidateAsync(request, It.IsAny<CancellationToken>()))
.ReturnsAsync(result);
var sut = new UseCase(uowMock.Object, repositoryMock, validatorMock.Object) as IUseCaseHandler<Request, Response>;
//Act
Func<Task> act = () => sut.HandleAsync(request);
//Assert
await act.Should().NotThrowAsync();
Mock.Get(repositoryMock).Verify(repo => repo.SaveAsync(It.IsAny<object>()), Times.Never);
}

Categories