使用 Moq 时在 Dapper 方法上获取 NotSupportedException
Getting NotSupportedException on Dapper method when using Moq
使用 Moq
时出现以下异常:
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>())'
我的class:
public class MyClass
{
public int Id {get; set;}
public string Name {get; set;}
}
我的实际 BI class。我为此 class
使用 Dapper
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);
}
我的单元测试:
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>())'
我只想模拟 Query<MyClass>
方法 。
我做错了什么?
Query<T>
是一种扩展方法。
public static IEnumerable<T> Query<T>(
this IDbConnection cnn,
string sql,
object param = null,
SqlTransaction transaction = null,
bool buffered = true
)
Moq 但是不能模拟扩展方法。因此,要么模拟该扩展方法内部完成的工作,这将涉及必须去检查 Dapper source code.
或
将该功能封装在您控制并可以模拟的抽象背后。
我倾向于将外部库与我自己的对象包装在一起,以使测试变得容易并使语言变得有趣。此外,您将这些库中的潜在更改隔离到包装对象。此外,您还可以快速向您的方法添加缓存等功能。但最重要的是,因为它涉及到这个问题,你可以很容易地模拟它。
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;
}
}
现在您可以完全控制模拟您的 IDatabase。
var mockDb = new Mock<IDatabase>();
mockDb.Setup(s=>s.Query(It.IsAny<>...whatever params...).Returns(...whatever you want to return...)
使用 Moq
时出现以下异常:
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>())'
我的class:
public class MyClass
{
public int Id {get; set;}
public string Name {get; set;}
}
我的实际 BI class。我为此 class
使用Dapper
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);
}
我的单元测试:
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>())'
我只想模拟 Query<MyClass>
方法 。
我做错了什么?
Query<T>
是一种扩展方法。
public static IEnumerable<T> Query<T>(
this IDbConnection cnn,
string sql,
object param = null,
SqlTransaction transaction = null,
bool buffered = true
)
Moq 但是不能模拟扩展方法。因此,要么模拟该扩展方法内部完成的工作,这将涉及必须去检查 Dapper source code.
或
将该功能封装在您控制并可以模拟的抽象背后。
我倾向于将外部库与我自己的对象包装在一起,以使测试变得容易并使语言变得有趣。此外,您将这些库中的潜在更改隔离到包装对象。此外,您还可以快速向您的方法添加缓存等功能。但最重要的是,因为它涉及到这个问题,你可以很容易地模拟它。
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;
}
}
现在您可以完全控制模拟您的 IDatabase。
var mockDb = new Mock<IDatabase>();
mockDb.Setup(s=>s.Query(It.IsAny<>...whatever params...).Returns(...whatever you want to return...)