1

I'm struggling a bit with one of my tests.

Here is the code I'm testing

public async Task Handle(ReceiveEventsFromSalesForceCommand message, IMessageHandlerContext context)
{
    var queryResult = await this.GenerateQueryResultAsync(message).ConfigureAwait(false);

    await this.DetermineActionAsync(context, queryResult).ConfigureAwait(false);
}

public async Task<QueryResult<EventStore__c>> GenerateQueryResultAsync(ReceiveEventsFromSalesForceCommand message)
{
    QueryResult<EventStore__c> queryResult;
    if (string.IsNullOrWhiteSpace(message.NextRecordsUrl))
        {
            queryResult = await this.forceClient.QueryAsync<EventStore__c>(query).ConfigureAwait(false);
            this.log.Info($"AFTER: QueryAllAsync<EventStore>(query), found {queryResult?.TotalSize ?? 0} records");
        }
        else
        {
            queryResult = await this.forceClient.QueryContinuationAsync<EventStore__c>(message.NextRecordsUrl).ConfigureAwait(false);
            this.log.Info("AFTER: QueryContinuationAsync<EventStore>(query)");
        }
    return queryResult;
}

And this is my unit test

[TestMethod]
    public async Task Test()
    {
        // arrange
        var forceConfig = Substitute.For<ISalesForceCreationHandlerConfig>();
        var forceClient = Substitute.For<IForceClient>();
        forceClient.QueryAllAsync<EventStore__c>(Arg.Any<string>()).Returns(Task.FromResult(new QueryResult<EventStore__c> { NextRecordsUrl = "Dummy" }));
        var messageHandlerContext = Substitute.For<IMessageHandlerContext>();
        var handler = new SalesForceBatchCreationHandler(forceClient, null, forceConfig);

        // act
        await handler.Handle(new ReceiveEventsFromSalesForceCommand(), messageHandlerContext);

        // assert
        await messageHandlerContext.Received().Send(Arg.Is<ReceiveEventsFromSalesForceCommand>(command => string.IsNullOrWhiteSpace(command.NextRecordsUrl)), Arg.Any<SendOptions>());
        await messageHandlerContext.DidNotReceive().SendLocal(Arg.Any<PublishMultipleKlantManagementEnvelopeCreatedEventsCommand>());
    }

My problem is that iresult of my GenerateQueryResultAsync method is null and I get a NullReferenceException. How can I make sure the result is not null and avoid the Exception?

Ronald Rozema
  • 236
  • 3
  • 16
  • 1
    Side note: in your first method `Handle` it would be more efficient to omit async/await. Just return the task directly as there is no reason to await its completion in that method (unless there is something you are not showing us in the method). – Igor Feb 09 '17 at 13:55
  • 1
    Is there a reason why this should not be closed as a duplicate of http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it ? What makes your case special that you cannot simply have a non-null value where you need it? – nvoigt Feb 09 '17 at 13:58
  • 1
    Are you using NSubstitute 1.9.0 or higher? Looks like you're stubbing `QueryAllAsync` but SUT is calling `QueryAsync`. – Stephen Cleary Feb 10 '17 at 02:30
  • @StephenCleary Thanks, I completely missed that detail. That fixed it haha – Ronald Rozema Feb 10 '17 at 08:32

1 Answers1

0

Restructure the way you make your async calls. Most probably this {queryResult.TotalSize} is the culprit.

public async Task<QueryResult<EventStore__c>> GenerateQueryResultAsync(ReceiveEventsFromSalesForceCommand message) {
    QueryResult<EventStore__c> queryResult;
    if (string.IsNullOrWhiteSpace(message.NextRecordsUrl)) {
        queryResult = await this.forceClient.QueryAsync<EventStore__c>(query).ConfigureAwait(false);
        this.log.Info($"AFTER: QueryAllAsync<EventStore>(query), found {queryResult?.TotalSize ?? 0} records");
    } else {
        queryResult = await this.forceClient.QueryContinuationAsync<EventStore__c>(message.NextRecordsUrl).ConfigureAwait(false);
        this.log.Info("AFTER: QueryContinuationAsync<EventStore>(query)" );
    }
    return queryResult;
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • I have edited the handle method, I need the queryresult as input for another method. queryResult.TotalSize was indeed the culprit. But the queryresult it returns is now null. I get the feeling I'm missing some sort of configuration in my unit test? – Ronald Rozema Feb 09 '17 at 14:32
  • @RonaldRozema then you need to review/debug the `forceClient.QueryAsync` method to see why it is returning null. Something in that method is cause a null result to be returned. – Nkosi Feb 09 '17 at 15:27