【发布时间】:2020-08-05 17:37:11
【问题描述】:
我正在尝试对 ASP.NET Core Web 控制器进行单元测试。下面是简单的数据访问的样子:
var database = configuration.GetSection("MongoDb:Database").Value;
var mongoSettings = new MongoCollectionSettings() { AssignIdOnInsert = true };
var users = client.GetDatabase(database).GetCollection<User>("User", mongoSettings);
var user = users.Find(u => u.EmailAddress == emailAddress).SingleOrDefault();
这很好用。它不容易进行单元测试(Find 不能用 Moq 模拟),我更喜欢间接层而不是我的数据访问,所以我尝试像这样重构为存储库类:
public interface IRepository<T>
{
T SingleOrDefault(Func<T, bool> predicate);
}
public class MongoRepository<T> : IRepository<T>
{
// ...
public T SingleOrDefault(Func<T, bool> predicate)
{
var objects = client.GetDatabase(this.databaseName).GetCollection<T>(this.repositoryName, this.settings);
var toReturn = objects.Find(o => predicate(o) == true).SingleOrDefault();
return toReturn;
}
}
当我将控制器更新为使用 MongoRepository<User> 时,它会抛出:
var usersRepo = new MongoRepository<User>(this.configuration, this.client);
var user = usersRepo.SingleOrDefault(u => u.EmailAddress == emailAddress);
具体来说,在存储库代码中,objects.Find(o => predicate(o) == true).SingleOrDefault(); 抛出异常:An exception of type 'System.InvalidOperationException' occurred in MongoDB.Driver.dll but was not handled in user code: 'Invoke(value(System.Func2[AutoDungeoners.Web.Models.User,System.Boolean]), {document}) 不受支持。'`
我不确定如何解决这个问题。我怀疑我的谓词定义为Func<T, bool> 不正确,因为如果我只调用objects.Find(o => true),它会毫无问题地返回第一个对象。
下面的完整异常堆栈。
An exception of type 'System.InvalidOperationException' occurred in MongoDB.Driver.dll but was not handled in user code: 'Invoke(value(System.Func`2[AutoDungeoners.Web.Models.User,System.Boolean]), {document}) is not supported.'
at MongoDB.Driver.Linq.Translators.PredicateTranslator.GetFieldExpression(Expression expression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(BinaryExpression binaryExpression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate[TDocument](Expression`1 predicate, IBsonSerializer`1 parameterSerializer, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.ExpressionFilterDefinition`1.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.MongoCollectionImpl`1.CreateFindOperation[TProjection](FilterDefinition`1 filter, FindOptions`2 options)
at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass41_0`1.<FindSync>b__0(IClientSessionHandle session)
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)
at MongoDB.Driver.IAsyncCursorSourceExtensions.SingleOrDefault[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
at MongoDB.Driver.IFindFluentExtensions.SingleOrDefault[TDocument,TProjection](IFindFluent`2 find, CancellationToken cancellationToken)
【问题讨论】:
-
EmailAddress的类型是什么?只是出于好奇,如果您尝试简化为var toReturn = objects.Find(predicate).SingleOrDefault();我不知道它是如何构建查询的,但我想知道它是否不喜欢您调用谓词而不是仅将其作为参数提供。 -
@ScottHannen
EmailAddress只是一个字符串。我认为objects.Find(predicate)无法编译,因为它试图将System.Something.Expression<Func<User, bool>>>转换为Func<User, bool>。 -
在传递之前将
Func转换为表达式怎么样? stackoverflow.com/questions/767733/… -
@ScottHannen 会导致相同的异常。
标签: c# mongodb asp.net-core mongodb-.net-driver