I am currently trying to implement MediatR in my project covering with tests. I want to cover if handler's Handle is called when sending a request.
I have this query
public class GetUnitsQuery : IRequest<List<UnitResponse>>
{
}
Handler:
public class GetUnitsHandler : IRequestHandler<GetUnitsQuery, List<UnitResponse>>
{
readonly IUnitRepository UnitRepository;
readonly IMapper Mapper;
public GetUnitsHandler(IUnitRepository unitRepository, IMapper mapper)
{
this.UnitRepository = unitRepository;
Mapper = mapper;
}
public async Task<List<UnitResponse>> Handle(GetUnitsQuery request, CancellationToken cancellationToken)
{
return Mapper.Map<List<UnitResponse>>(UnitRepository.GetUnits());
}
}
Send request from the controller:
var result = await Mediator.Send(query);
Any ideas how to test if a Handler is called when specified with a specific Query using MoQ?
Like others said in the comments, you don't need to test the internals of Mediator.
Your test boundary is your application, so assuming a controller along the lines of:
public class MyController : Controller
{
private readonly IMediator _mediator;
public MyController(IMediator mediator)
{
_mediator = mediator;
}
public async IActionResult Index()
{
var query = new GetUnitsQuery();
var result = await Mediator.Send(query);
return Ok(result);
}
}
I would verify Mediator is called like this:
public class MyControllerTests
{
[SetUp]
public void SetUp()
{
_mockMediator = new Mock<IMediator>();
_myController = new MyController(_mockMediator.Object)
}
[Test]
public async void CallsMediator()
{
// Arranged
_mockMediator.SetUp(x=> x.Send(It.IsAny<GetUnitsQuery>()))
.Returns (new List<UnitResponse>());
// Act
await _myController.Index();
// Assert
_mockMediator.Verify(x=> x.Send(It.IsAny<GetUnitsQuery>()), Times.Once);
}
}
I have not used MoQ to check the Received calls to a specific handler. However if I would use Nsubsitute and SpecFlow, I would do something like this in my test.
var handler = ServiceLocator.Current.GetInstance<IRequestHandler<GetUnitsQuery, List<UnitResponse>>>();
handler.Received().Handle(Arg.Any<GetUnitsQuery>(), Arg.Any<CancellationToken>());
Related
I am new to Integration test, I have a controller which has IMediator and I am using Moq framework for the integration test.
The issue I am having is that I keep getting null in the response when trying to mock MediatR. Before trying to mock MediatR, I tried to mock a service (in this case IUserService) and it worked perfectly (the return type for the Delete controller and other methods was bool).
Since I am now using IMediator in the controller so trying to change the integration test to mock MediatR, I can do integration test for the handler which has IUserService but I am trying to test the whole pipeline. Below is what I have in terms of code starting from the controller to the integration test.
//Controller
private IMediator _mediator;
public UserController(IMediator mediator)
{
_mediator = mediator;
}
[HttpDelete("{id}")]
public async Task<ActionResult<Result<Unit>>> DeleteUser(int id)
{
return await _mediator.Send(new DeleteUserCommand { UserId = id });
}
public class DeleteUserCommand : IRequest<Result<Unit>> {public int UserId { get; set; }}
//Command handler
public class DeleteUserCommandHandler : IRequestHandler<DeleteUserCommand, Result<Unit>>
{
private readonly IUserService _userService;
public DeleteUserCommandHandler(IUserService userService)
{
_userService = userService;
}
public async Task<Result<Unit>> Handle(DeleteUserCommand request, CancellationToken cancellationToken)
{
return await _userService.DeleteUser(request.UserId);
}
}
//Service layer
public async Task<Result<Unit>> DeleteUser(int userId)
{
var userExist = await _context.Users.FirstOrDefaultAsync(x => x.Id == userId);
if (userExist == null) return Result<Unit>.Failure("User Id doesn't exsist");
_context.Remove(userExist);
var result = await _context.SaveChangesAsync() > 0;
return Result<Unit>.Success(Unit.Value);
}
//Integration test
[TestFixture]
public class UserControllerTests
{
private readonly Mock<IMediator> _mockMediator;
private UserController _userController;
public UserControllerTests()
{
_mockMediator = new Mock<IMediator>();
}
[Test]
public async Task DeleteUser_NotSuccessful_NoIdDeleted()
{
Result<Unit> expected = new Result<Unit>();
_mockMediator.Setup(x => x.Send(It.IsAny<DeleteUserCommand>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(expected));
_userController = new UserController(_mockMediator.Object);
var result = await _userController.DeleteUser(6);
Assert.AreEqual("User Id doesn't exsist", result?.Value?.Error);
}
}
//Response in the integration test
I have two UserIds 6 and 7
UserId 6: doesn't exsist so I am expecting a message saying id doesn't exsist but the current response I am getting is null.
UserId 7: does exsist and expecting something like IsSuccess: true which is a custom code I added
Note: the attached code for the test is just for user Id 6.
You might notice in the code above starting from the controller, part of the return type is Result which is a custom class I added and below is the code.
public class Result<T>
{
public bool IsSuccess { get; set; }
public T Value { get; set; }
public string Error { get; set; }
public static Result<T> Success(T value) => new Result<T> { IsSuccess = true, Value = value };
public static Result<T> Failure(string error) => new Result<T> { IsSuccess = false, Error = error };
}
`
I am trying to find out what I have done wrong with mocking MediatR and why it keep returning null.
Thanks for the help in advance.
First thing I tried to do integration test mock the IUserService then switched to IMediator then started to get null in the response when doing integration test. I tried to google the issue but no luck.
I have consumer CarCreatedConsumer which I want to unit test
public class CarCreatedConsumer: IConsumer<CarCreatedEvent>
{
private readonly IMediator _mediator;
public CarCreatedConsumer(IMediator mediator)
{
_mediator = mediator;
}
public async Task Consume(ConsumeContext<CarCreatedEvent> context)
{
....
}
}
Using MassTransit.Testing I'm trying to write test for event consumer
[TestFixture]
public class MyTests
{
private ServiceProvider _provider;
private InMemoryTestHarness _harness;
[SetUp]
public void SetUp()
{
_provider = new ServiceCollection()
.AddMassTransitInMemoryTestHarness(cfg =>
{
cfg.AddConsumer<CarCreatedConsumer>();
}).AddMediator()
.BuildServiceProvider(true);
_harness = _provider.GetRequiredService<InMemoryTestHarness>();
}
[Test]
public async Task MessageShouldBeConsumed()
{
await _harness.Start();
try
{
await _harness.InputQueueSendEndpoint.Send<CarCreatedEvent>(new
{
CarId = Guid.NewGuid.ToString(),
CarOwnerName = "John Stuart"
...
}
// Always false
Assert.True(_harness.Consumed.Select<CarCreatedEvent>().Any());
}
finally
{
await _harness.Stop();
}
}
}
I'm expect this to return true but it fails (returns false). Obviously I'm doing something wrong, any ideas?
Your test harness usage is suspect, and is also using an obsolete version of the configuration. I'd suggest reading the documentation on the current test harness and how to test your consumer.
I am a totally newbie to Mediator pattern and Moq. I have an API controller that has an async task method and want to mock this method
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class UsersController : UsersControllerBase
{
private readonly IMediator _mediator;
public UsersController(IMediator mediator)
{
this._mediator = mediator;
}
[HttpGet("GetUsers")]
public async Task<ActionResult<ICollection<User>>> GetUsers(CancellationToken cancellationToken)
{
var result = await _mediator.Send(new UserGetRequest(),
cancellationToken).ConfigureAwait(false);
return DataOrProblem(result);
}
}
I am trying to create or mock this method and not sure how to do it? Here is what I have tried
public class GetUsersTest
{
//Arrange
private readonly Mock<IMediator> _mediator = new Mock<IMediator>();
private readonly Mock<UsersController> _sut;
public GetUsersTest()
{
_sut = new Mock<UsersController>(_mediator);
}
}
If the controller is the subject under test then do not mock it. Create an actual instance, injecting the mocked mediator.
public class UsersControllerTest {
public async Task GetUsersTests() {
//Arrange
Mock<IMediator> mediator = new Mock<IMediator>();
UsersController sut = new UsersController(mediator.Object);
//... setup the behavior of the mocked mediator
ICollection<User> expected = //...provide fake data here
mediator
.Setup(s => s.Send<UserGetRequest>(It.IsAny<UserGetRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(expected);
//Act
ActionResult<ICollection<User>> result = await sut.GetUsers(CancellationToken.None);
//Assert
//assert the expected behavior with what actually happened
}
}
I have created small kind of xunit test case but I don't know how to create this controller which i have mention below.
public class PropertyController : ControllerBase
{
private readonly IMediator _mediator;
private readonly ILogger<PropertyController> _logger;
public PropertyController(IMediator mediator, ILogger<PropertyController> logger)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task<IActionResult> AddProperty([FromBody] AddPropertyCommand command)
{
bool commandResult = false;
_logger.LogInformation(
"----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({#Command})",
command.GetGenericTypeName(),
nameof(command.ModifiedUserId),
command.ModifiedUserId,
command);
commandResult = await _mediator.Send(command);
if (!commandResult)
{
return BadRequest();
}
return Ok();
}
I have created like this. i have mock the dependency and create a test case for add command is working fine or not
public class PropertyControllerTest
{
private readonly PropertyController _it;
private readonly Mock<IMediator> _mediatorMock;
private readonly Mock<ILogger<PropertyController>> _loggerPropertycontrollerMock;
public PropertyControllerTest()
{
_mediatorMock = new Mock<IMediator>();
_loggerPropertycontrollerMock = new Mock<ILogger<PropertyController>>();
_it = new PropertyController(_mediatorMock.Object, _loggerPropertycontrollerMock.Object);
}
[Fact]
public void it_Should_add_information_successfully_and_returns_200_status_result()
{
//How can i write xunit test case. I'm creating like this
_mediatorMock.Setup(x => x.Send().Returns(property);
}
The test below covers the 200 status result - a similar test for bad requests would be very similar.
[Fact]
public void it_Should_add_information_successfully_and_returns_200_status_result()
{
// Arrange
var expected = new AddPropertyCommand();
_mediatorMock.Setup(x => x.Send(It.IsAny<AddPropertyCommand>())).Returns(true);
// Act
var actionResult = _it.AddProperty(expected);
// Assert
actionResult.ShouldBeAssignableTo<OkResult>();
_mediatorMock.Verify(x => x.Send(expected));
}
N.B. actionResult.ShouldBeAssignableTo<OkResult>(); is written using the Shouldly assertion framework, you can swap that out for anything you like. The one built into XUnit would be like this: Assert.IsType(typeof(OkResult), actionResult);
I need to create a unit test for the following class's InvokeAsync method. What it merely does is calling a private method in the same class which includes complex logical branches and web service calls. But the unit test are written only for the public methods. So what should I do in this scenario? What should I test in here? Any suggestions would be greatly appreciated.
public class MyCustomHandler
{
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public MyCustomHandler(HttpClient client, ILogger logger)
{
_httpClient = httpClient;
_logger = logger;
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
// Lot of code with complex logical branches and calling web services.
}
}
If your testing framework supports it (MsTest does) you can declare your test method async and call the method from there. I'd mock the web services using a mock framework such as Rhino Mocks so you don't need to depend on the actual web service.
public interface IWebService
{
Task<bool> GetDataAsync();
}
[TestClass]
public class AsyncTests
{
[TestMethod]
public async void Test()
{
var webService = MockRepository.GenerateStub<IWebService>();
webService.Expect(x => x.GetDataAsync()).Return(new Task<bool>(() => false));
var myHandler = new MyCustomHandler(webService);
bool result = await myHandler.InvokeAsync();
Assert.IsFalse(result);
}
}
[TestMethod]
public async void TestWebServiceException()
{
var webService = MockRepository.GenerateStub<IWebService>();
webService.Expect(x => x.GetDataAsync()).Throw(new WebException("Service unavailable"));
var myHandler = new MyCustomHandler(webService);
bool result = await myHandler.InvokeAsync();
Assert.IsFalse(result);
}