1

I am new to unit testing,

I am working on a minimal API project. and I am testing an endpoint with xunit, moq

endpoint class - ParticipantsGetAll.cs

public class ParticipantsGetAll : IEndpoint<IResult, GetAllParticipantsRequest>
{
    const string uri = "api/participants-all";
    private ParticipantService? participantService;

    public void AddRoute(IEndpointRouteBuilder app)
    {
        app.MapPost(uri, async ( ParticipantService participantService, [FromBody] GetAllParticipantsRequest query) => 
        {
            this.participantService = participantService;
            return await HandleAsync(query);
        })
        .Produces<List<ParticipantSummaryModel>>()
        .WithTags("Participants")
        .WithName("GetAllParticipants");
    }

    public async Task<IResult> HandleAsync( GetAllParticipantsRequest query)
    {
        var participants = await participantService!.ListAllAsync(query);
        return Results.Ok(participants);
    }

I tried to write a unit test test above endpoint class.

CreateParticipantApiTest.cs

    [Fact]
    public async void ListAllAsyncShouldReturn200Status()
    {
        var query = new GetAllParticipantsRequest()
        {
           Name= "",
            KeyCordinator="",
            RelatedConnection="",
            Statuses = null

        };
        var participant = ParticipantMockData.NewParticipantModel(); // a static class

        var sut = new ParticipantsGetAll();
        var result = (OkObjectResult)await sut.HandleAsync(query);

        result.StatusCode.Should().Be(200);

    }

I got below error

Message:  System.NullReferenceException : Object reference not set to an instance of an object.
Stack Trace:  ParticipantsGetAll.HandleAsync(GetAllParticipantsRequest query) line 36 CreateParticipantApiTest.ListAllAsyncShouldReturn200Status() line 67

I have no idea why the object tis null.

Please anyone help me to find the problem. I am facing this issue for a long time

Thanks

1 Answer 1

1

I have no idea why the object tis null.

That is pretty clear, because in your unit test you invoke HandleAsync directly, so the setup which you have moved into MapPost does not happen (compiler was trying to help but was shut down with null-forgiving operator in participantService!.ListAllAsync(query)). Also I'm pretty sure this way of using handlers can lead to some concurrency problems (if ParticipantService is a scoped service). Move ParticipantService participantService to HandleAsync. Something along this lines (not tested):

public class ParticipantsGetAll : IEndpoint<IResult, GetAllParticipantsRequest>
{
    const string uri = "api/participants-all";

    public void AddRoute(IEndpointRouteBuilder app)
    {
        app.MapPost(uri, HandleAsync)
        .Produces<List<ParticipantSummaryModel>>()
        .WithTags("Participants")
        .WithName("GetAllParticipants");
    }

    public async Task<IResult> HandleAsync(ParticipantService participantService, [FromBody] GetAllParticipantsRequest query)
    {
        var participants = await participantService.ListAllAsync(query);
        return Results.Ok(participants);
    }
}

And modify the test accrodingly.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Can I create a constructor inside ParticipantsGetAll like below. public ParticipantsGetAll(ParticipantService participantService) { this.participantService = participantService; }
@hanushi you can but there is no point in doing so in current code structure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.