I want to Create Xunit test for this controller. How can i do that - c#

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);

Related

Testing MassTransit consumer with mediator

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.

How to mock Imediator pattern controller that returns ActionResult<ICollection<Course>> GetResult(CancellationToken)

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
}
}

MediatR and CQRS testing. How to verify that handler is called?

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>());

Dependency Injection with XUnit Mediatr and IServiceCollection

Currently I'm able to handle IServiceCollection to inject mocks for particular services in the following manner.
public class TestClass
{
private IMediator _mediatr;
private void SetupProvider(IUnitOfWork unitOfWork, ILogger logger)
{
configuration = new ConfigurationBuilder().Build();
_services = new ServiceCollection();
_services.AddSingleton(configuration);
_services.AddScoped(x => unitOfWork);
_services.AddSingleton(logger);
_services.AddMediatR(Assembly.Load("Application"));
_services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggerBehaviour<,>));
_mediator = _services.BuildServiceProvider().GetService<IMediator>();
}
[Fact]
public async void UnitTest_Success()
{
var unitOfWork = new Mock<IUnitOfWork>();
var logger = new Mock<ILogger>();
SetupProvider(unitOfWork.Object, logger.Object);
var fixture = new Fixture();
var command = fixture.Create<MediatorCommand>();
unitOfWork.Setup(x => x.Repository.FindAll(It.IsAny<IList<long>>(), It.IsAny<bool?>()))
.ReturnsAsync(new List<Domain.Model>());
var response = await _mediatr.Send(command);
using (new AssertionScope())
{
response.Should().NotBeNull();
response.IsSuccess.Should().BeTrue();
}
}
}
For the following subject under test
public class MediatorCommand : IRequest<CommandResponse>
{
public string Name { get; set ;}
public string Address { get; set; }
}
public class MediatorCommandHandler : IRequestHandler<MediatorCommand, CommandResponse>
{
private readonly ILogger _logger;
private readonly IUnitOfWork _unitOfWork;
public MediatorCommandHandler(IUnitOfWork unitOfWork, ILogger logger)
{
_logger = logger;
_unitOfWork = unitOfWork;
}
public async Task<CommandResponse> Handle(MediatorCommand command, CancellationToken cancellationToken)
{
var result = new CommandResponse { IsSuccess = false };
try
{
var entity = GetEntityFromCommand(command);
await _unitOfWork.Save(entity);
result.IsSuccess = true;
}
catch(Exception ex)
{
_logger.LogError(ex, ex.Message);
}
return result;
}
}
This test runs fine and the unitOfWork and logger mocks are used in the command handlers.
I'm try to move this so that the IServiceCollection construction happens per class instead of each test using the following:
public class SetupFixture : IDisposable
{
public IServiceCollection _services;
public IMediator Mediator { get; private set; }
public Mock<IUnitOfWork> UnitOfWork { get; private set; }
public SetupFixtureBase()
{
UnitOfWork = new Mock<IUnitOfWork>();
configuration = new ConfigurationBuilder().Build();
_services = new ServiceCollection();
_services.AddSingleton(configuration);
_services.AddScoped(x => UnitOfWork);
_services.AddSingleton(new Mock<ILogger>().Object);
_services.AddMediatR(Assembly.Load("Application"));
_services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggerBehaviour<,>));
Mediator = _services.BuildServiceProvider().GetService<IMediator>();
}
public void Dispose()
{
Mediator = null;
_services.Clear();
_services = null;
}
}
public class TestClass : IClassFixture<SetupFixture>
{
protected readonly SetupFixture _setupFixture;
public UnitTestBase(SetupFixture setupFixture)
{
_setupFixture = setupFixture;
}
[Fact]
public async void UnitTest_Success()
{
var fixture = new Fixture();
var command = fixture.Create<MediatorCommand>();
_setupFixture.UnitOfWork.Setup(x => x.Repository.FindAll(It.IsAny<IList<long>>(), It.IsAny<bool?>()))
.ReturnsAsync(new List<Domain.Model>());
var response = await _mediatr.Send(command);
using (new AssertionScope())
{
response.Should().NotBeNull();
response.IsSuccess.Should().BeTrue();
}
}
}
Unfortunately with this method my mocks do not get injected on the command handler. Is there a way to get this to work?
Thank you,
I found the issue and it is not related to moving to IClassFixuture<>. The issue was that I was initializing Mediator on a base class an then adding the mock UnitOfWork on a derived class.
This cause the Mediator initialization to fail because one of the beheviours expected the UnitOfWork which at the time was not yet on the container.
Moving the initialization of Mediator after all the services have been added helped me resolve the issue and now all works as expected.
If you try the same thing, please make sure to include all the services in the container before initializing any objects that require those dependencies.
Thank you all those who had input.

Moq: setup a generic method with mocked parameters

I've been trying to write a few tests in NUnit for my generic methods, without success. I hope I can make my situation clear, since I had to heavily paraphrase my code.
DoBusinessLogic() is the method I want to test. It calls two other methods from the base class:
public class MySvc : BaseSvc, IMySvc
{
private readonly IMyRepo _repo;
private readonly IMyConnectorClass _connector
public MySvc(IMyRepo repo) : base(repo)
{
_repo = repo;
_connector = _repo.GetConnector();
}
public async Task DoBusinessLogic(int id1, int id2){
bool doesFirstObjectExist = await CheckMainObjExists<Foo>(id1, _connector);
await CheckSubObjExists<Bar>(id2, _connector);
// further business logic
}
}
Those methods, in turn, call the same repository method, but have different logic after it:
public abstract class BaseSvc : IBaseSvc
{
private readonly IBaseRepo _repo
protected BaseSvc(IBaseRepo repo)
{
_repo = repo;
}
protected async Task<bool> CheckMainObjExists<T>(int? id, IMyConnectorClass connector)
{
return await _repo.GetObjectByIdAsync<T>(Id, connector) != null;
}
protected async Task CheckSubObjExists<T>(int? id, IMyConnectorClass connector)
{
if (await _repo.GetObjectByIdAsync<T>(Id, connector) == null)
{ throw new Exception("Object not found!"); }
}
}
Next, I want to write unit a test for DoBusinessLogic() in the MySvc class. Unfortunately, it seems I can't mock the responses from the repository.
[TestFixture]
public class MySvcTests
{
private MySvc _svc;
private Mock<IMyRepo> _repoMock;
private Mock<IMyConnectorClass> _connectorMock;
[SetUp]
public void SetUp()
{
_repoMock = new Mock<IMyRepo>() {};
_connectorMock = new Mock<IMyConnectorClass>();
_repo.SetUp(r => r.GetConnector()).Return(_connectorMock.Object);
_svc = new MySvc(_repoMock);
}
/*
My intent in this test, is to make CheckMainObjExists() pass,
but make CheckSubObjExist() fail.
*/
[Test]
public async Task DoBusinessLogic_If2ndObjectNotExist_ThrowException()
{
// This should return an object
_repoMock.Setup(r => r.GetObjectByIdAsync<Foo>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync(new Foo());
// This should return null
_repoMock.Setup(r => r.GetObjectByIdAsync<Bar>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync((Bar) null);
Assert.Throws<Exception>(await _svc.DoBusinessLogic());
}
}
However, when I run the test, both methods that I set up for my mock repo return null, whereas I expect a "true" from the first.
I do not know where the problem is situated, but I have my suspicions:
Is it possible to setup a method, using a mocked object as a parameter? In this case, is it possible to use _connectorMock.Object as a setup parameter?
Is it possible to setup the same generic method multiple times, but for a different type each time? It's first setup for Foo, then for Bar.
I just tested this code and it runs as expected. Now I had to make a lot of assumptions just to get the code to compile and run which would mean that my test of your code is flawed as I may have fixed something that was omitted in your example.
I made no changes to your test setup code, which worked.
[TestClass]
public class MySvcTests {
[TestMethod]
[ExpectedException(typeof(Exception))]
public async Task DoBusinessLogic_If2ndObjectNotExist_ThrowException() {
var _repoMock = new Mock<IMyRepo>() { };
var _connectorMock = new Mock<IMyConnectorClass>();
_repoMock.Setup(r => r.GetConnector()).Returns(_connectorMock.Object);
var _svc = new MySvc(_repoMock.Object);
// This should return an object
_repoMock.Setup(r => r.GetObjectByIdAsync<Foo>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync(new Foo());
// This should return null
_repoMock.Setup(r => r.GetObjectByIdAsync<Bar>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync((Bar)null);
await _svc.DoBusinessLogic(0, 0);
}
}

Categories

Resources