简体   繁体   中英

Getting NotSupportedException on Dapper method when using Moq

When using Moq I'm getting this exception below:

System.NotSupportedException: 'Expression references a method that does not belong to the mocked object: c => c.Query<MyClass>(It.IsAny<String>(), It.IsAny<Object>(), It.IsAny<IDbTransaction>(), It.IsAny<Boolean>(), It.IsAny<Nullable`1>(), (Nullable`1)It.IsAny<CommandType>())'

My class:

public class MyClass
{
    public int Id {get; set;}
    public string Name {get; set;}
}

My actual BI class. I'm using Dapper for this class

using Dapper;

//**
//**
//**
using (var con = _readRepository.CreateConnection())
{
    var query = "Select * FROM myTable"
    return con.Query<MyClass>(query, new { Skip = 0, Take = 10}, null, true, null, null);
}

My Unit Test:

var conMock = new Mock<IDbConnection>();

IEnumerable<MyClass> listModels = new List<MyClass>().AsEnumerable();

//The exception occurrs right here
conMock.Setup(c => c.Query<MyClass>(
        It.IsAny<string>(),
        It.IsAny<object>(),
        It.IsAny<IDbTransaction>(),
        It.IsAny<bool>(),
        It.IsAny<int?>(),
        It.IsAny<CommandType>()
))
.Returns(() => listModels);

//System.NotSupportedException: 'Expression references a method that does not belong to the mocked object: c => c.Query<MyClass>(It.IsAny<String>(), It.IsAny<Object>(), It.IsAny<IDbTransaction>(), It.IsAny<Boolean>(), It.IsAny<Nullable`1>(), (Nullable`1)It.IsAny<CommandType>())'

What I'm only trying to do is to mock Query<MyClass> method . What am I doing wrong?

Query<T> is an extension method.

public static IEnumerable<T> Query<T>(
    this IDbConnection cnn, 
    string sql, 
    object param = null, 
    SqlTransaction transaction = null, 
    bool buffered = true
)

Moq however can't mock extension methods. So either mock what is done internally in that extension method, which would involve having to go inspect the Dapper source code .

or

encapsulate that functionality behind an abstraction you control and can mock.

I tend to wrap external libraries with my own objects to make testing easy and language to taste. Furthermore, you insulate potential changes in those libraries to the wrapping object. Also, you can quickly add functionality such as caching to your methods. But most importantly as it relates to this question, you can easily mock it.

public interface IDatabase{

IDbConnection GetConnection();
IEnumerable<T> Query<T>(whatever you want here...exactly Dapper's parameters if necessary);

}

public class Database : IDatabase{
     //implement GetConnection() however you like...open it too!
     public IEnumerable<T> Query<T>(...parameters...){

     IEnumerable<T> query = null;
     using(conn = this.GetConnection()){
          query = conn.Query<T>()//dapper's implementation
     }
     return query;
   }
}

Now you can mock your IDatabase with total control.

var mockDb = new Mock<IDatabase>();
mockDb.Setup(s=>s.Query(It.IsAny<>...whatever params...).Returns(...whatever you want to return...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM