Search code examples
c#unit-testingintegration-testingnservicebus

How to mock out IEndpointInstance of NServiceBus


I have the controller below which communicates via NServiceBus IEndpointInstance (full duplex response/request solution). I would like to test validation placed in this controller, so I need to pass through an IEndpointInstance object. Unfortunately, there is no mention about this in the documentation in Particular's site that I could find.

In the NServiceBus.Testing nuget package I found the TestableEndpointInstance class, but I don't know how to use it.

I have the test code below and it compiles, but it just hangs when I run it. I think something is wrong around TestableEndpointInstance parametrization.

Could someone help me out with an example?

Controller:

public CountryController(
    IEndpointInstance endpointInstance,
    IMasterDataContractsValidator masterDataContractsValidator)
{
    this.endpointInstance = endpointInstance;
    this._masterDataContractsValidator = masterDataContractsValidator;
}

[HttpPost]
[Route("Add")]
public async Task<HttpResponseMessage> Add([FromBody] CountryContract countryContract)
{
    try
    {
        CountryRequest countryRequest = new CountryRequest();
        this._masterDataContractsValidator.CountryContractValidator.ValidateWithoutIdAndThrow(countryContract);

        countryRequest.Operation = CountryOperations.Add;
        countryRequest.CountryContracts.Add(countryContract);

        // nservicebus communication towards endpoint

        return message;
    }
    catch (Exception e)
    {
        var message = this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, e.Message);
        return message;
    }
}

Test:

public CountryControllerTests()
{
    TestableEndpointInstance endpointInstance = new TestableEndpointInstance();
    // Validator instantiation
    this.countryController = new CountryController(endpointInstance, masterDataContractsValidator);
}


[Theory]
[MemberData("CountryControllerTestsAddValidation")]
public async void CountryControllerTests_Add_Validation(
    int testId,
    CountryContract countryContract)
{
    // Given

    // When
    Func<Task> action = async () => await this.countryController.Add(countryContract);

    // Then
    action.ShouldThrow<Exception>();
}

Solution

  • I added doco for IEndpointInstance https://docs.particular.net/samples/unit-testing/#testing-iendpointinstance-usage

    Given a controller

    public class MyController
    {
        IEndpointInstance endpointInstance;
    
        public MyController(IEndpointInstance endpointInstance)
        {
            this.endpointInstance = endpointInstance;
        }
    
        public Task HandleRequest()
        {
            return endpointInstance.Send(new MyMessage());
        }
    }
    

    Can be tested with

    [Test]
    public async Task ShouldSendMessage()
    {
        var endpointInstance = new TestableEndpointInstance();
        var handler = new MyController(endpointInstance);
    
        await handler.HandleRequest()
            .ConfigureAwait(false);
    
        var sentMessages = endpointInstance.SentMessages;
        Assert.AreEqual(1, sentMessages.Length);
        Assert.IsInstanceOf<MyMessage>(sentMessages[0].Message);
    }