UnoSD / Moq.Dapper

Moq extensions for Dapper methods.
GNU General Public License v2.0
173 stars 78 forks source link

NullReferenceException when returning null from ReturnsAsync #51

Open GreenDavidA opened 4 years ago

GreenDavidA commented 4 years ago

I am trying to mock out a dependency that uses Dapper, and I want it to return null. Normally, when I am using Moq, I will cast the null as the return type, and it works. When I do that here, I am getting a System.NullReferenceException.

The code is as follows:

    [Fact]
    public async Task Test1()
    {
        Mock<IDbConnection> connection = new Mock<IDbConnection>();

        connection
            .SetupDapperAsync(m => m.QueryAsync<SampleTable>(It.IsAny<string>(), null, null, null, null))
            .ReturnsAsync((IEnumerable<SampleTable>)null);

        var actual = connection.Object.QueryAsync<SampleTable>("").GetAwaiter().GetResult().ToList();
    }

The exception returned is: Message: System.NullReferenceException : Object reference not set to an instance of an object. Stack Trace: DbDataReaderFactory.DbDataReader[TResult](Func1 result) <>cDisplayClass2_01.<SetupQueryAsync>b__1() <>c__DisplayClass2_02.b1() --- End of stack trace from previous location where exception was thrown --- Extensions.InvokePreserveStack(Delegate del, Object[] args) ReturnLazyValueResponse.RespondTo(Invocation invocation) MethodCall.Execute(Invocation invocation) FindAndExecuteMatchingSetup.Handle(Invocation invocation, Mock mock) IInterceptor.Intercept(Invocation invocation) Interceptor.Intercept(IInvocation invocation) AbstractInvocation.Proceed() DbCommandProxy.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) SqlMapper.QueryAsync[T](IDbConnection cnn, Type effectiveType, CommandDefinition command) line 419 TableDomainTests.Test1() line 148 --- End of stack trace from previous location where exception was thrown ---`

I do have a workaround. In place of returning a null, I return an empty List and it does work.

    [Fact]
    public async Task Test1()
    {
        Mock<IDbConnection> connection = new Mock<IDbConnection>();

        connection
            .SetupDapperAsync(m => m.QueryAsync<SampleTable>(It.IsAny<string>(), null, null, null, null))
            .ReturnsAsync(new List<SampleTable>());

        var actual = connection.Object.QueryAsync<SampleTable>("").GetAwaiter().GetResult().ToList();
    }

I just wanted to bring it to your attention.

LuizPanariello commented 4 years ago

QueryAsync method isn't working with null, it always expect a IEnumerable object and iterates over it.

At DbDataReaderFactory it needs to do something like this to work:

            var result = resultFunc();
            if (result == null)
                return new DataTableReader(new DataTable());
balpreetpatil commented 3 years ago

I can confirm, it still has this issue. using Moq.Dapper, Version=1.0.4