C# 使用IMongoQueryable进行单元测试。System.InvalidCastException:无法将EnumerableQuery类型的对象强制转换为IOrderedMongoQueryable类型
我使用GetAll()方法提供了以下服务,并编写了测试该方法的测试C# 使用IMongoQueryable进行单元测试。System.InvalidCastException:无法将EnumerableQuery类型的对象强制转换为IOrderedMongoQueryable类型,c#,asp.net-core,moq,mongodb-.net-driver,C#,Asp.net Core,Moq,Mongodb .net Driver,我使用GetAll()方法提供了以下服务,并编写了测试该方法的测试 public partial class DocumentTypeService : IDocumentTypeService { private readonly IRepository<DocumentType> _documentTypeRepository; private readonly IMediator _mediator; public Do
public partial class DocumentTypeService : IDocumentTypeService
{
private readonly IRepository<DocumentType> _documentTypeRepository;
private readonly IMediator _mediator;
public DocumentTypeService(IRepository<DocumentType> documentTypeRepository, IMediator mediator)
{
_documentTypeRepository = documentTypeRepository;
_mediator = mediator;
}
public virtual async Task<IList<DocumentType>> GetAll()
{
var query = from t in _documentTypeRepository.Table
orderby t.DisplayOrder
select t;
return await query.ToListAsync();
}
}
您能解释一下为什么类型不可查询,以及如何解决这个问题吗?谢谢新(2020-09-15)
我尽可能地重复你的努力。有两个问题
首先,您的GetAll()
方法包含一个orderby
,这就是迫使IMongoQueryable
变成IOrderedMongoQueryable
的原因。但是,\u mongoqueryalemock
不会返回IOrderedMongoQueryable
。如果您尝试用IOrderedMongoQueryable
替换\u mongoqueryalemock
的IMongoQueryable
,也会失败。我没有找到方法获取\u expectedQueryable
以允许IOrderedQueryable
其次,异步可能会给您带来麻烦。如果没有Async,我可以将GetAll()
查询更改为类似以下内容,这将在应用orderby之前解析查询:
public List GetAll()
{
var query=来自_documentTypeRepository.Table.ToList()中的t
orderby t.DisplayOrder
选择t;
返回query.ToList();
}
但是,我没有找到管理ToListSync的方法
总而言之,我回到了我最初的建议。不要试图嘲笑我的不可质疑。将服务更改为接受MongoClient。无论哪种方式,您都在嘲笑Mongo,但接受IMongoClient时,您直接使用它,而不是将它隐藏在另一个抽象背后
private只读IMongoClient\u mongoClient;
公共文档类型服务(IMongoClient mongoClient){…}
原创(2020-09-14)
我不能完全确定,但我相信这是因为\u documentTypeRepository
没有返回IMongoQueryable
。它返回一个表
,这将强制一个有序的mongo查询
为了使用我描述的模拟方法进行此操作,\u documentTypeRepository
需要返回IMongoQueryable,然后转换为表
,或者查看IQueryable是否可以转换为IORDeredMongoryable
简言之,没有什么可以嘲笑IOrderedMongoQueryable
的返回
老实说,这一切都表明存储库与实现的耦合可能过于紧密。强制IMongoQueryable
到IQueryable
是一种代码气味和反模式。您可以考虑以两种方式之一重新考虑服务和/或知识库层:
\u documentTypeRepository.GetAll()
方法,将MongoDb结果映射到DocumentType
。或GetAll
方法的一部分从Mongo返回数据,并映射到那里的DocumentType谢谢。我有以下设置来返回表的正确值:_documentTypeRepositoryMock.setup(x=>x.Table).Returns(_mongoQueryableMock.Object);
[TestClass()]
public class DocumentTypeServiceTests
{
private Mock<IRepository<DocumentType>> _documentTypeRepositoryMock;
private DocumentTypeService _documentTypeService;
private Mock<IMediator> _mediatorMock;
private Mock<IMongoQueryable<DocumentType>> _mongoQueryableMock;
private List<DocumentType> _expected;
private IQueryable<DocumentType> _expectedQueryable;
[TestInitialize()]
public void Init()
{
_mediatorMock = new Mock<IMediator>();
_documentTypeRepositoryMock = new Mock<IRepository<DocumentType>>();
_mongoQueryableMock = new Mock<IMongoQueryable<DocumentType>>();
_expected = new List<DocumentType>
{
new DocumentType() {Name = "name1", Description = "t1", DisplayOrder = 0},
new DocumentType() {Name = "name2", Description = "t2", DisplayOrder = 1}
};
_expectedQueryable = _expected.AsQueryable();
_mongoQueryableMock.Setup(x => x.ElementType).Returns(_expectedQueryable.ElementType);
_mongoQueryableMock.Setup(x => x.Expression).Returns(_expectedQueryable.Expression);
_mongoQueryableMock.Setup(x => x.Provider).Returns(_expectedQueryable.Provider);
_mongoQueryableMock.Setup(x => x.GetEnumerator()).Returns(_expectedQueryable.GetEnumerator());
_documentTypeRepositoryMock.Setup(x => x.Table).Returns(_mongoQueryableMock.Object);
_documentTypeService = new DocumentTypeService(_documentTypeRepositoryMock.Object, _mediatorMock.Object);
}
[TestMethod()]
public async Task GetAllDocumentTypes()
{
var actual = await _documentTypeService.GetAll();
Assert.AreEqual(_expected.Count, actual.Count);
}
}
Message:
Test method Grand.Services.Tests.Documents.DocumentTypeServiceTests.GetAllDocumentTypes threw exception:
System.InvalidCastException: Unable to cast object of type 'System.Linq.EnumerableQuery`1[Grand.Domain.Documents.DocumentType]' to type 'MongoDB.Driver.Linq.IOrderedMongoQueryable`1[Grand.Domain.Documents.DocumentType]'.
Stack Trace:
MongoQueryable.OrderBy[TSource,TKey](IMongoQueryable`1 source, Expression`1 keySelector)
DocumentTypeService.GetAll() line 38
DocumentTypeServiceTests.GetAllDocumentTypes() line 101
ThreadOperations.ExecuteWithAbortSafety(Action action)