Giter Club home page Giter Club logo

moq.dapper's Introduction

Moq.Dapper

Moq extensions for Dapper methods.

NuGet Version and Downloads count

Example usage

Mocking a call to Query with a simple type:

[Test]
public void QueryGeneric()
{
    var connection = new Mock<IDbConnection>();

    var expected = new[] { 7, 77, 777 };

    connection.SetupDapper(c => c.Query<int>(It.IsAny<string>(), null, null, true, null, null))
              .Returns(expected);

    var actual = connection.Object.Query<int>("", null, null, true, null, null).ToList();

    Assert.That(actual.Count, Is.EqualTo(expected.Length));
    Assert.That(actual, Is.EquivalentTo(expected));
}

Mocking a call to Query with a complex type:

[Test]
public void QueryGenericComplexType()
{
    var connection = new Mock<IDbConnection>();

    var expected = new[]
    {
        new ComplexType { StringProperty = "String1", IntegerProperty = 7 },
        new ComplexType { StringProperty = "String2", IntegerProperty = 77 },
        new ComplexType { StringProperty = "String3", IntegerProperty = 777 }
    };

    connection.SetupDapper(c => c.Query<ComplexType>(It.IsAny<string>(), null, null, true, null, null))
              .Returns(expected);

    var actual = connection.Object.Query<ComplexType>("", null, null, true, null, null).ToList();

    Assert.That(actual.Count, Is.EqualTo(expected.Length));

    foreach (var complexObject in expected)
    {
        var match = actual.Where(co => co.StringProperty == complexObject.StringProperty && co.IntegerProperty == complexObject.IntegerProperty);

        Assert.That(match.Count, Is.EqualTo(1));
    }
}

Mocking a call to ExecuteScalar:

[Test]
public void ExecuteScalar()
{
    var connection = new Mock<IDbConnection>();

    const int expected = 77;

    connection.SetupDapper(c => c.ExecuteScalar<int>(It.IsAny<string>(), null, null, null, null))
              .Returns(expected);

    var actual = connection.Object.ExecuteScalar<int>("", null, null, null);

    Assert.That(actual, Is.EqualTo(expected));
}

Mocking a call to QueryAsync

[Test]
public async Task QueryAsyncGeneric()
{
    var connection = new Mock<DbConnection>();

    var expected = new[] { 7, 77, 777 };

    connection.SetupDapperAsync(c => c.QueryAsync<int>(It.IsAny<string>(), null, null, null, null))
              .ReturnsAsync(expected);

    var actual = (await connection.Object.QueryAsync<int>("", null, null, null, null)).ToList();

    Assert.That(actual.Count, Is.EqualTo(expected.Length));
    Assert.That(actual, Is.EquivalentTo(expected));
}

Mocking a call to ExecuteScalarAsync:

[Test]
public void ExecuteScalarAsync()
{
    var connection = new Mock<DbConnection>();
    
    const string expected = "Hello";

    connection.SetupDapperAsync(c => c.ExecuteScalarAsync<object>(It.IsAny<string>(), null, null, null, null))
              .ReturnsAsync(expected);

    var actual = connection.Object
                           .ExecuteScalarAsync<object>("")
                           .GetAwaiter()
                           .GetResult();

    Assert.That(actual, Is.EqualTo(expected));
}

moq.dapper's People

Contributors

ajaysoni-cap avatar andread84 avatar anth12 avatar faniereynders avatar honzakuzel1989 avatar javenwang avatar jhgoodwin avatar jpepiot avatar ltmenezes avatar oppewala avatar ricochetbrown avatar ross2411 avatar smokedlinq avatar tewr avatar tjrobinson avatar tombatron avatar tvanfosson-il avatar unosd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

moq.dapper's Issues

NullReferenceException when using .Callback

I have tried to attach a callback method to assert generated SQL sent.

            connectionMock
                .SetupDapperAsync(x => x.QueryAsync<Instant StartTime, long SecondCount)>(
                    It.IsAny<string>(),
                    It.IsAny<Parameters>(),
                    null, null, null))
                .Callback(
                    (string sql, Parameters, IDbTransaction transaction, int? commandTimeOut, CommandType? commandType) =>
                    {
                        // Assert
                    })
                .ReturnsAsync(new (Instant StartTime, long SecondCount)[0]);

I get the message System.NullReferenceException : Object reference not set to an instance of an object. on the same line as connectionMock.SetupDapperAsync is called.

Is this supported ?

The other parts work, if I remove the .Callback function everything runs fine

License GPLv2 to MIT, BSD or Apache2

Hello, Is it posible to modify the license to MIT, BSD or Apache2?, Moq is under BSDv3 and it's posible to use it with commercial private software, but it's incompatible to use this library in this scenarios.

License forbids linking with proprietary code

It seems that this library is published under GPL-2.0 license which forbids linking with proprietary (non-GPL compatible) code. Is this intentional?

I would like to use this library in my work, but I wouldn't want to get into any legal problems because of that.

ArgumentNullException when i pass an array as a parameter

I got an argument null error when i tried to use an array as an sql parameter

var ids = new[] {1, 2, 3};
var result = connection.Query<Model>("SELECT * FROM TABLE WHERE id in @IDS", new {  IDS =  ids });

Debuging dapper i found that `command.CommandText' is null on SqlMapper class, what is causing this
image

Support DynamicParameters and Output Parameters

Currently there is no support for Dynamic Parameters. Dapper uses a different code path for this object type over the anonymous object type. Additionally, it uses an outputCallback to fill in any parameters that are output types. Because there is no persistent mock for non-templated variables, each time Dapper tries to append a parameter to the query, it gets a new Parameters collection instead, causing an NRE. This needs to be solved for.

byte[] fields are not mapped

I would like to mock a sql query that contains a NVARBINARY column but properties with the type byte[] are not mapped.

vs2017 nuget Install failed.

Attempting to gather dependency information for package 'Moq.Dapper.1.0.3' with respect to project 'serviceTests', targeting '.NETFramework,Version=v4.5.2'
Gathering dependency information took 1.29 sec
Attempting to resolve dependencies for package 'Moq.Dapper.1.0.3' with DependencyBehavior 'Lowest'
Resolving dependency information took 0 ms
Resolving actions to install package 'Moq.Dapper.1.0.3'
Resolved actions to install package 'Moq.Dapper.1.0.3'
Retrieving package 'Moq.Dapper 1.0.3' from 'nuget.org'.
Install failed. Rolling back...
Package 'Moq.Dapper.1.0.3' does not exist in project 'serviceTests'
Package 'Moq.Dapper.1.0.3' does not exist in folder 'F:\Temp\testmywcfs1\packages'
Executing nuget actions took 466.93 ms
Install-Package : Could not install package 'Moq.Dapper 1.0.3'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.5.2', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, co
ntact the package author.
At line:1 char:1

  • Install-Package Moq.Dapper -Version 1.0.3
  •   + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
      + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    
    

Time Elapsed: 00:00:02.2250492

ExecuteAsync with parameter

I'm using Moq.Dapper for my unit tests, however when i used with parameter, throw exception "Object reference not set to an instance of an object"

Example:

var connection = new Mock<DbConnection>();
connection.SetupDapperAsync(c => c.ExecuteAsync(It.IsAny<string>(), It.IsAny<UsuarioInfo>(), It.IsAny<DbTransaction>(), null, null)).ReturnsAsync(0);

await connection.Object.ExecuteAsync("@Login", new { Login = "test"}, null);

Can you help me?

Nullable types don't get set

I've got complex objects which have nullable types (ie int?, DateTimeOffSet?). The Moq.Dapper extension for QueryAsync seems to set these all to null instead of their value. I attempted a PR to fix this because I noticed you are restricting the types to non-null types. Adding nullable types just throws an exception in Dapper though.
Any ideas?

SetupDapperAsync() on Dapper ExecuteAsync() method throws NotSupportedException

The following code causes a SystemNotSupportedException:

var mockDbConn = new Mock<IDbConnection>();
mockDbConn.SetupDapperAsync(x => x.ExecuteAsync(It.IsAny<string>(), 
    It.IsAny<object>(),
    It.IsAny<IDbTransaction>(),
    It.IsAny<int?>(),
    It.IsAny<CommandType?>())
).ReturnsAsync(1);

Not sure what is causing the issue. Any suggestions?

ExecuteAsync() result doesn't match expected value specified in setup

When passing a collection of values to ExecuteAsync(), the integer value returned by ExecuteAsync() is a multiple of the value specified in the call to ReturnsAsync().

Below is a modified copy of the DapperExecuteAsyncTest unit test from the Moq.Dapper.Test project. The expected value of "result" is 3; instead, a value of 9 is received, and the test fails.

If the testData argument is omitted from the call to ExecuteAsync(), the value of "result" is 3 and the test passes.

This behavior is problematic when unit testing a function that passes a collection in a call to ExecuteAsync() while mocking DbConnection; The integer returned by ExecuteAsync() should match the value specified in the call to .ReturnsAsync().

    [Test]
    public void ExecuteAsync()
    {
        var connection = new Mock<DbConnection>();

        var testData = new int [] { 7, 77, 777 };

        connection.SetupDapperAsync(c => c.ExecuteAsync("", null, null, null, null))
                  .ReturnsAsync(testData.Length);

        // Specifying **testData** as the second argument causes this test to fail.
        var result = connection.Object
                               .ExecuteAsync("", testData)
                               .GetAwaiter()
                               .GetResult();

        // The result should be 3; instead, a value of 9 is returned and this test fails.
        Assert.That(result, Is.EqualTo(testData.Length));
    }

QueryAsync with multiple types does not work

`var results = await connection.QueryAsync(
"[dbo].[GetSomething]",
types: new[]
{
typeof(Something),
typeof(ASubThing),
typeof(AnotherSubThing)
},
map: objects =>
{
var result = objects[0] as Something?? new Something();

                result.FirstSubThing= objects[1] as ASubThing?? new ASubThing();
                result.SecondSubThing= objects[2] as AnotherSubThing?? new AnotherSubThing();

                return result;
            },
            dbArgs,
            commandType: CommandType.StoredProcedure);`

moq.dapper continues to give an error saying that (When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id (Parameter 'splitOn') even though the code works fine when the api is running.

.ThrowsAsync doesn't appear to work

I am trying to simulate a query throwing an exception. So I can test how my code handles this.

I am doing a setup along the lines of

dbConnectionMock.SetupDapperAsync(mock =>
                        mock.QueryAsync<RowModel>(
                            It.IsAny<string>(),
                            It.IsAny<object>(),
                            null,
                            null,
                            null))
                    .ThrowsAsync(new Exception("error executing db query"));

The code errors whilst performing this setup and throws an exception with the following message:
One or more errors occurred. (error executing db query)

It appears almost as if my dummy exception is being thrown during the setup.

Am I doing something wrong?
Or is .ThrowsAsync not supported?

Thanks for making this library it is very useful
Tom

Accessing the params argument in the ReturnsAsync

If I call a query with parameters is there currently anyway to access those values in the ReturnsAsync method?
I need to access the data in my tests and store it for another query to use it.

Thanks

Is this project no longer under maintenance?

When will they be able to review the pullrequests and update the library? Or is it abandoned? If so, they could confirm us to create a fork and publish a corrected version in nuget. Currently I have problems with enumerators returning zero

Suggestion: Add query resolver to handle all mocks

I suggest instead of coding up mock methods for every permutation of what is needed that a resolver system be added.

The idea works like this:

  • Register a resolver with the mock, returning generic of T matching Query and other related methods
  • Resolver accepts a query sql, parameters, then returns the resolved output.

One possible such implementation would be a resource driven resolver. Store the queries, the parameter values, then resolve those to query outputs. If no query can be resolved, the resource resolver should tell the user that the resources do not contain the query/parameter combination, and how to fix it. Then, the answer to mocking would be to put in known query results for known query inputs. In a later date, if you change the query, or inputs, the match will be broken allowing you to take action to fix it.

Thoughts?

I was looking to work on such an idea and wondered if you would be interested in adding it to your repo if I did a PR.

While mocking for Exception the methods are not returning the Exception.

Am trying to mock the Dapper method to return the Exception but it actually returning 0 rows instead the exception.
Here is the sample code

mockConnection.SetupDapper(c => c.Query<Student>(It.IsAny<string>(), null, null, true, null, null))
                      .Throws<InvalidOperationException>();
            mockDatabase.Setup(x => x.GetConnection()).Returns(mockConnection.Object);

            var repository = new StudentRepository(mockDatabase.Object);

            // Act
            var actual = repository.Get(); 

It Should return a InvalidOperationException but instead its returning zero rows from Query<Student>

Doesn't support the latest version of Moq

I get this error when I try to use Moq.Dapper with the latest version of Moq.

Assembly 'Moq.Dapper' with identity 'Moq.Dapper, Version=1.0.3.0, Culture=neutral, PublicKeyToken=null' uses 'Moq, Version=4.12.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920' which has a higher version than referenced assembly 'Moq' with identity 'Moq, Version=4.7.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920'

Not moq methods with generic type

var connection = new Mock<IDbConnection>();

    var expected = new[]
    {
        new ComplexType { StringProperty = "String1", IntegerProperty = 7 }
    };

connection.SetupDapper(c => c.Query<ComplexType>(It.IsAny<string>(), null, null, true, null, null)) .Returns(expected);

////actual  will not null
var actual = connection.Object.Query<ComplexType>("", null, null, true, null, null);
   
////Now try moq Query with any new type
    connection.SetupDapper(c => c.Query<NewTestType>(It.IsAny<string>(), null, null, true, null, null)) .Returns(new [] { new NewTestType()} );

////actual  will be null
actual = connection.Object.Query<ComplexType>("", null, null, true, null, null)

Strange little null bug for Nullable enum types in complex types.

So I have an object like this:

public class CptExtension
    {
        public int Id { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
        public bool Active { get; set; }
        public DateTime EffectiveDate { get; set; }
        public DateTime? RetireDate { get; set; }
        public CodeClassification? CodeClassification { get; set; }
        public IList<EdsModifier> DisallowedModifiers { get; set; } = new List<EdsModifier>();
        public Subcategory? SubCategory { get; set; }
        public ContrastSetting? ContrastSetting { get; set; }
        public BusinessUsage? BusinessUsage { get; set; }
        public FamilyIndicator? FamilyIndicator { get; set; }
        public MultiProcCode? MultiProcCode { get; set; }
    }

I have setup my mapping with this:

        public void SetupDapperCalls(int? id = null, string code = null, object model = null)
        {
            if (id.HasValue)
            {
                DbConnection.SetupDapperAsync(c => c.QueryAsync<CptExtension>(It.IsAny<string>(), null, null, null, CommandType.StoredProcedure))
                    .ReturnsAsync(CptExtensions.Where(x => x.Id == id.Value));
                return;
            }

            if (!string.IsNullOrWhiteSpace(code))
            {
                DbConnection.SetupDapperAsync(c =>
                        c.QueryAsync<CptExtension>(It.IsAny<string>(), null, null, null, CommandType.StoredProcedure))
                    .ReturnsAsync(CptExtensions.Where(x => x.Code.Equals(code, StringComparison.OrdinalIgnoreCase)));
                return;
            }

            if (model != null)
            {
                return;
            }

            DbConnection.SetupDapperAsync(c =>
                    c.QueryAsync<CptExtension>(It.IsAny<string>(), null, null, null, CommandType.StoredProcedure))
                .ReturnsAsync(CptExtensions);
        }

When the test call is made, the nullable enum types all return null. So my subsequent query integrity checks all fail, since the data is corrupted in transit. Now I know this is the fault of the mapping, but it shouldn't be there at all, my expected values should be unaltered as a result of the mock mapping. So, any ideas?

NullReferenceException when returning null from ReturnsAsync

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)
<>c__DisplayClass2_01.<SetupQueryAsync>b__1() <>c__DisplayClass2_02.b__1()
--- 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.

When writing a test for query which has .Any method it throws an error Value cannot be null

There are a couple of queries in my repository that use Any() for dapper. While I was writing the unit test for it they all fail with the same error Value cannot be null.

Sample code

This is the method which I want to test

public IEnumerable<SiteRemotePrefixResponse> CheckIfPrefixExistsForSiteIds(string siteIds, DateTimeOffset startDateTime, DateTimeOffset endDateTime)
        {
            var query = string.Empty;
            var responses = Enumerable.Empty<SiteRemotePrefixResponse>();

            using (var dbConnection = Connection.CreateDbConnection())
            {
                dbConnection.Open();

                query = $@"SELECT siteId,
                           CASE COUNT(prefix) WHEN 0 THEN 0 ELSE 1 END AS isAvailable
                           FROM ABC
                           WHERE site_id = ANY(@SiteId)
                           AND bucket_start BETWEEN '{startDateTime.DateTime:yyyy-MM-dd HH:mm:ss}' AND '{endDateTime.DateTime:yyyy-MM-dd HH:mm:ss}'
                           GROUP BY site_id
                           ORDER BY 2 DESC
                        ";

                var siteArray = siteIds.Split(',');
                var parameters = new { SiteId = siteArray };

                responses = dbConnection.Query<SiteRemotePrefixResponse>(query, parameters, commandTimeout: 600);
            }

            return responses;
        }

Unit test for this method


[Fact]
        public void CheckIfRemotePrefixExistsForSiteIds_OkResult()
        {
            //ARRANGE
            var siteIds = "'SIT-1234','SIT-3456'";
            var startDateTime = DateTime.Now.AddDays(-1);
            var endDateTime = DateTime.Now;
            var siteRemotePrefixResponses = MockedEntitiesRepository.mockedSiteRemotePrefixResponses;
            var siteArray = siteIds.Split(',');
            var parameters = new { SiteId = siteArray };
            mockedDbConnection.SetupDapper(x => x.Query<SiteRemotePrefixResponse>(It.IsAny<string>(), parameters, null, true, 600, null)).Returns(siteRemotePrefixResponses);


            //ACT
            var result = repository.CheckIfRemotePrefixExistsForSiteIds(siteIds, startDateTime, endDateTime);

            //ASSERT
            Assert.Equal(JsonConvert.SerializeObject(siteRemotePrefixResponses), JsonConvert.SerializeObject(result));
        }

This is the stacktrace

   at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator)
   at System.Text.RegularExpressions.Regex.Replace(String input, String pattern, MatchEvaluator evaluator, RegexOptions options)
   at Dapper.SqlMapper.PackListParameters(IDbCommand command, String namePrefix, Object value) in C:\projects\dapper\Dapper\SqlMapper.cs:line 2086
   at Dapper.CommandDefinition.SetupCommand(IDbConnection cnn, Action`2 paramReader) in C:\projects\dapper\Dapper\CommandDefinition.cs:line 129
   at Dapper.SqlMapper.<QueryImpl>d__138`1.MoveNext() in C:\projects\dapper\Dapper\SqlMapper.cs:line 1078
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in C:\projects\dapper\Dapper\SqlMapper.cs:line 723
   at XCASystemAPI.Core.Repository.CheckIfRemotePrefixExistsForSiteIds(String siteIds, DateTimeOffset startDateTime, DateTimeOffset endDateTime) in Repository.cs:line 366
   at SystemAPI.Tests.API.RepositoryTest.CheckIfRemotePrefixExistsForSiteIds_OkResult() in RepositoryTest.cs:line 149

Kindly suggest what could be done to solve this error.

Could not install using .Net 4.5 or above

Sorry, my bad, it's only available for Net Standard 2.0.

I'm trying to install the latest version (1.0.0.4) using .Net 4.5 from Nuget, but I can't.
This is the error from Visual Studio Output.

Error | ย  | Could not install package 'Moq.Dapper 1.0.0.4'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.5', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

Thanks!

Do not support for multimapping

Am trying to mock multimapping using this library and am not getting the support for the same.
Here is the multi mapping query.
`string sql = "SELECT * FROM Invoice AS A INNER JOIN InvoiceDetail AS B ON A.InvoiceID = B.InvoiceID;";

using (var connection = My.ConnectionFactory())
{
connection.Open();

var invoices = connection.Query<Invoice, InvoiceDetail, Invoice>(
        sql,
        (invoice, invoiceDetail) =>
        {
            invoice.InvoiceDetail = invoiceDetail;
            return invoice;
        },
        splitOn: "InvoiceID")
    .Distinct()
    .ToList();

}`

Am trying to Mock this using the below code but am not able to achieve this? Can you resolve this as this methods everybody uses.
mockConnection.SetupDapper(c => c.Query<Invoice, InvoiceDetail, Invoice>(It.IsAny<string>(), null, null, null, true, "", null)) .Returns(fakeInvoice);

Dapper Does not work with IDbTransaction

When trying to moq with moq.dapper using an IDbTransaction, It seems to call but won't return the "returns".

Using the same call, I pass a null to the setup and the actual call, the returns works.

Mocking SqlMapper.QueryFirstOrDefault call is not supported

code

var userPermissions = new RaPermission[0];
var user = new RaUser()
{
    UserId = 1,
    UserEmail = "UserEmail",
    Permissions = userPermissions.ToList()
};

dbMock.SetupDapper(x => x.QueryFirstOrDefault<RaUser>(It.IsAny<string>(), It.IsAny<object>(), null, null, null))
    .Returns(user);

stack trace

   at Moq.Dapper.DbConnectionInterfaceMockExtensions.SetupDapper[TResult](Mock`1 mock, Expression`1 expression)
   at RAPMD.Web.Tests.Auth.UserServiceTests.GetByIdExistsUserTest() in D:\EPAM\RAPMD\source\RAPMD.Web.Tests\Auth\UserServiceTests.cs:line 59

image

ExecuteScalarAsync does not work with specific type in generic parameter.

Hi,
the example with object in ExecuteScalarAsync generic works well (xUnit version)

[Fact()]
public async Task ExecuteScalarAsyncTest()
{
    var connection = new Mock<DbConnection>();
    const string expected = "Hello";
    connection.SetupDapperAsync(c => c.ExecuteScalarAsync<object>(It.IsAny<string>(), null, null, null, null))
              .ReturnsAsync(expected);
    var actual = await connection.Object.ExecuteScalarAsync<object>("");
    Assert.Equal(actual, expected);
}

but when I change object to desired specific type, e.g. string the test throws exception in SetupDapperAsyncMethod

[Fact()]
public async Task ExecuteScalarAsyncTest()
{
    var connection = new Mock<DbConnection>();
    const string expected = "Hello";
    connection.SetupDapperAsync(c => c.ExecuteScalarAsync<string>(It.IsAny<string>(), null, null, null, null))
              .ReturnsAsync(expected);
    var actual = await connection.Object.ExecuteScalarAsync<string>("");
    Assert.Equal(actual, expected);
}

with followed message

  Message: 
    System.InvalidCastException : Unable to cast object of type 'Castle.Proxies.ISetup`2Proxy' to type 'Moq.Language.Flow.ISetup`2[System.Data.Common.DbConnection,System.Threading.Tasks.Task`1[System.String]]'.
  Stack Trace: 
    DbConnectionMockExtensions.SetupDapperAsync[TResult](Mock`1 mock, Expression`1 expression)

NullReferenceException when using parameters

Dapper throws a NullReferenceException when parameters are used in a command.

Given the following test scenario, the exception occurs:

[Test]
public void ExecuteScalar()
{
    var connection = new Mock<IDbConnection>();

    const int expected = 77;

    connection.SetupDapper(c => c.ExecuteScalar<int>(It.IsAny<string>(), It.IsAny<object>(), null, null, null))
              .Returns(expected);

    var actual = connection.Object.ExecuteScalar<int>(
        "select * from people where id = @id", new { id = 1 }, null, null);

    Assert.That(actual, Is.EqualTo(expected));
}

Stack trace:

   at ParamInfo44e2be98-d8bb-4358-8537-1dc2da8dc716(IDbCommand , Object )
   at Dapper.CommandDefinition.SetupCommand(IDbConnection cnn, Action`2 paramReader)
   at Dapper.SqlMapper.ExecuteScalarImpl[T](IDbConnection cnn, CommandDefinition& command)
   at Dapper.SqlMapper.ExecuteScalar[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable`1 commandTimeout, Nullable`1 commandType)

When no parameters are used in the command, it works.

After investigation I found this

It turns out that Dapper internally needs to add parameters to the IDbCommand.Parameters collection and this is currently null.

ExecuteScalarAsync does not work mocked like IDbConnection.

Hi,
when I try mock ExecuteScalarAsync method in IDbConnection mock

[Fact()]
public async Task ExecuteScalarAsyncTest()
{
    var connection = new Mock<IDbConnection>();
    const string expected = "Hello";
    connection.SetupDapperAsync(c => c.ExecuteScalarAsync<object>(It.IsAny<string>(), null, null, null, null))
              .ReturnsAsync(expected);
    var actual = await connection.Object.ExecuteScalarAsync<object>("");
    Assert.Equal(actual, expected);
}

the code throws following excpetion

  Message: 
    System.NotSupportedException : Specified method is not supported.
  Stack Trace: 
    DbConnectionInterfaceMockExtensions.SetupDapperAsync[TResult](Mock`1 mock, Expression`1 expression)

but when I change mock object to DbConnection

[Fact()]
public async Task ExecuteScalarAsyncTest()
{
    var connection = new Mock<DbConnection>();
    const string expected = "Hello";
    connection.SetupDapperAsync(c => c.ExecuteScalarAsync<object>(It.IsAny<string>(), null, null, null, null))
              .ReturnsAsync(expected);
    var actual = await connection.Object.ExecuteScalarAsync<object>("");
    Assert.Equal(actual, expected);
}

the code works. For QueryAsync both solution works without exceptions.

[Fact()]
public async Task ExecuteScalarAsyncTest()
{
    var connection = new Mock<IDbConnection>();
    string[] expected = new [] { "Hello" };
    connection.SetupDapperAsync(c => c.QueryAsync<string>(It.IsAny<string>(), null, null, null, null))
              .ReturnsAsync(expected);
    var actual = await connection.Object.QueryAsync<string>("");
    Assert.Equal(actual.Count(), expected.Count());
}

Doesn't support Moq verify

After doing something like this:

connection.SetupDapper(c => c.Query<int>(It.IsAny<string>(), It.IsAny<InvoiceLine>(), null, true, null, null)).Returns(new List<int>());

Then trying to do:

connection.Verify(s => s.Query<int>(It.IsAny<string>(), It.IsAny<InvoiceLine>(), null, true, null, null), Times.Exactly(invoice.InvoiceLines.Count()));

The verify fails with a hard error...it's understandable, because the Query method doesn't really exist. Is there any way to make a verify work?

Suggestion - convert main unit tests to dotnet core

I suggest you move the main unit tests to be dotnet core compatible and only move the DataContext code to exist outside as a Framework only and tests that rely on Framework. This will allow the main development to continue in dotnet core.

Related, not Issue - Created Repo and library from Entity Framework Test Library code

This is not an issue, but I thought you'd be interested to know this exists. If there is a better way to send such messages, I'd be glad to change my method.

I saw Entity Framework had similar code as this, but licensed differently. I took their code and created a library from it.

https://github.com/jhgoodwin/FakeDbProvider

I hope it's not seen as self promoting, because I did very little to it, other than add a build, publish a nuget package, fill in a few missing methods, then add one simple base class to use for creating tests.

Did not try it yet, but, you should be able to use this fake provider as a base for dapper, without issues.

John

Query on Complex Types that have Enums - don't work

If my complex type has an enum in it - that will normally map to an INT/ENUM pairing in the database to POCO query -- this returns always a zero.

			var expected = new[] {
				new FancyObject{Desired="2", DeviceGUID = Guid.Parse(validGUID),  Installed="1", ImageTypeID = ImageType.BODY_IMAGE},
				new FancyObject{Desired="4", DeviceGUID = Guid.Parse(validGUID),  Installed="3", ImageTypeID = ImageType.HEADER_IMAGE}
			};
			connection.SetupDapper(c => c.Query<FancyObject>(It.IsAny<string>(), null, null, true, null, null)).Returns(expected);

// using this, the "expected" object is returned, but the ENUM (ImageTypeID) is 0

Using that object above as a Returns -- the ImageTypeID (an enum in FancyObject, but an INT in DB -- returns 0 - always).

All the other fields return the right values -- just the ENUM conversion seems to fail - it's 0 when returning the expected.

Support async Dapper methods, e.g. QueryAsync

Hopefully the title is self explanatory. When using Moq.Dapper with QueryAsync an exception is thrown as it's not supported.

I have had a go at creating a PR for this but without much luck.

If you can give me an idea as to how you would approach it I can have another go.

Unable to chain ReturnsAsync with Verifiable

Hey, I am having some difficulty with one of my mocks. I want to do this:

var dbConnectionMock = new Mock<DbConnection>(MockBehavior.Loose);
dbConnectionMock.SetupDapperAsync(m =>
        m.QueryAsync(It.IsAny<string>(), It.IsAny<object>(), null, null, CommandType.StoredProcedure))
        .ReturnsAsync(new List<dynamic>()).Verifiable();

But when I do, I get NullReferenceException because somehow ReturnsAsync is returning null. I also can't do .Verifiable().ReturnsAsync(...) because Verifiable is void. (This seems like it shouldn't be affected by Moq.Dapper since this method is from the core library, but I can only reproduce this issue when using Moq.Dapper)

I have been able to get it working like this:

var dbConnectionMock = new Mock<DbConnection>(MockBehavior.Loose);
var mock = dbConnectionMock.SetupDapperAsync(m =>
        m.QueryAsync(It.IsAny<string>(), It.IsAny<object>(), null, null, CommandType.StoredProcedure));
mock.ReturnsAsync(new List<dynamic>());
mock.Verifiable();

But I'd rather not have to spread it out like that since usually the setup is chainable.

Any suggestions?

Needs SetupSequential Support.

If I need to use the same IDBConnection to make sequential calls within the scope of a given test, can one Mock object support multiple SetupDapper(db => db.Query()) calls. It appears not.

Version for .NET Core/Standard

Great library, exactly what I was looking for.

However its only available for full .NET. Is there a plan in place to make it available for .NET core or .NET standard ?

ExecuteAsync with StoredProcedure as command type

I get an exception when I try to mock the ExecuteAsync method with StoredProcedure as command type.

var connection = new Mock<DbConnection>();
connection.SetupDapperAsync(c => c.ExecuteAsync(It.IsAny<string>(), It.IsAny<int>(), null, null, null)).ReturnsAsync(10);
var result = await connection.Object.ExecuteAsync("sp_test", new { Id = 1 }, null, null, CommandType.StoredProcedure);
Result StackTrace:	
at ParamInfod786c014-bcd9-49cd-880d-6da8aec447ab(IDbCommand , Object )
   at Dapper.CommandDefinition.SetupCommand(IDbConnection cnn, Action`2 paramReader)
   at Dapper.SqlMapper.TrySetupAsyncCommand(CommandDefinition command, IDbConnection cnn, Action`2 paramReader)
   at Dapper.SqlMapper.ExecuteImplAsync(IDbConnection cnn, CommandDefinition command, Object param)
   at ConsoleApp1.MyTests.DoTest()
--- End of stack trace from previous location where exception was thrown ---
Result Message:	System.NullReferenceException : Object reference not set to an instance of an object.

Apparently, it seems that the 'DbParameterCollection' property and the 'CreateDbParameter' method are not mocked, so we get an exception when dapper try to access the Parameter property.
If I mock them in the function DbConnectionMockExtensions.SetupNonQueryCommandAsync by adding the following code, I can run my test without error.

   var commandMock = new Mock<DbCommand>();

            commandMock.Protected()
           .SetupGet<DbParameterCollection>(nameof(DbParameterCollection))
           .Returns(new Mock<DbParameterCollection>().Object);

            commandMock.Protected()
                       .Setup<DbParameter>("CreateDbParameter")
                       .Returns(new Mock<DbParameter>().Object);
           
            mockResult(commandMock, () => result);

Should I add the code and submit a PR ?

SetupDapperAsync does not work

Hi,

I am experiencing unexpected behaviour when using the non generic SetupDapperAsync method. I was following the last example form the readme (which is an example for generic setup) and it is working fine. If I correct the test as in the example below the actual variable holds empty list.

[Fact]
public async Task QueryAsync()
{
    // given
    var connection = new Mock<IDbConnection>();
    var expected = new[] { new { Id = 1, Name = "test1" }, new { Id = 2, Name = "test2" } };
    connection.SetupDapperAsync(c => c.QueryAsync(It.IsAny<string>(), null, null, null, null))
        .ReturnsAsync(expected);

    // when
    var actual = (await connection.Object.QueryAsync(string.Empty, null, null, null, null)).ToList();

    // then
    Assert.NotEmpty(actual);
}

Is it an issue or there is something wrong with my code?

Any chance of supporting Dapper.Contrib extension methods?

There are several Dapper functions exposed in Dapper.Contrib ...
T Get<T>(id);
IEnumerable<T> GetAll<T>();
int Insert<T>(T obj);
int Insert<T>(Enumerable<T> list);
bool Update<T>(T obj);
bool Update<T>(Enumerable<T> list);
bool Delete<T>(T obj);
bool Delete<T>(Enumerable<T> list);
bool DeleteAll<T>();

Are you thinking about support these methods?

Ability to Mock Multiple Dapper Calls at a Time

I am attempting to test a feature that relies on multiple QueryAsync; however, when apply the second setup, it overrides the first mock setup, even if T is different. I was hoping that it would work differently for different T's or by changing the SQL statement, but no luck. Code looks like this.

var mock = new Mock();
mock.SetupDapperAsync(c => c.QueryAsync(It.IsAny(), null, null, null, null)).ReturnsAsync(object1);
mock.SetupDapperAsync(c => c.QueryAsync(It.IsAny(), null, null, null, null)).ReturnsAsync(object2);

var expected = object1;
var actual = mock.Object.Query("", null, null, null, null).ToList(); // shows up as Object2.

I'll ask on SO to see if I'm missing something. Thanks for this great library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.