gpt4 book ai didi

.net - 单元测试 MongoDB.Driver dotnet core

转载 作者:行者123 更新时间:2023-12-03 15:59:37 24 4
gpt4 key购买 nike

我们正在使用命令/查询模式,其中实现详细了解 MongoDB 如何工作,我们想为此编写一个测试。模拟 MongoDb IMongoCollection<CarDocument>同时还要确保正确的 Find发送过滤器是相当具有挑战性的。我们使用 .NET core 2.1 和 MongoDB.Driver v2.7.2

using MongoDB.Driver;

namespace Example
{


public class SomeMongoThing : ISomeMongoThing
{
public IMongoCollection<CarDocument> GetCars()
{
var client = new MongoClient("ConnectionString");
var database = client.GetDatabase("DatabaseName");
return database.GetCollection<CarDocument>("CollectionName");
}
}

public interface ISomeMongoThing
{
IMongoCollection<CarDocument> GetCars();
}

public class GetCarQuery
{
private readonly ISomeMongoThing someMongoThing;

public GetCarQuery(ISomeMongoThing someMongoThing)
{
this.someMongoThing = someMongoThing;
}

public CarDocument Query(string aKey)
{
var schedules = someMongoThing.GetCars();

var match = schedules.Find(x => x.AKey == aKey);
return match.Any() ? match.First() : this.GetDefaultCar(schedules);
}

private CarDocument GetDefaultCar(IMongoCollection<CarDocument> schedules)
{
return schedules.Find(x => x.AKey == "Default").First();
}
}
}

我们在这里有一个测试,但我们无法编写一个测试来检查 aKey 是否正确。 -filter已被使用,意味着如果我们使用过滤器x => x.AKey == "hello"在实现中测试应该失败。即使代码有 .Find(x => true)测试通过。

using System.Collections.Generic;
using System.Threading;
using MongoDB.Driver;
using Moq;
using NUnit.Framework;

namespace Example
{
public class GetCarQueryTest
{
[Test]
public void ShouldGetByApiKey()
{
var mockCarDocument = new CarDocument();
var aKey = "a-key";

var result = Mock.Of<IAsyncCursor<CarDocument>>(x =>
x.MoveNext(It.IsAny<CancellationToken>()) == true
&& x.Current == new List<CarDocument>() { mockCarDocument });
var cars = Mock.Of<IMongoCollection<CarDocument>>(x => x.FindSync(
It.IsAny<FilterDefinition<CarDocument>>(),
It.IsAny<FindOptions<CarDocument, CarDocument>>(),
It.IsAny<CancellationToken>()) == result);

var someMongoThing = Mock.Of<ISomeMongoThing>(x => x.GetCars()() == cars);
var getCarQuery = new GetCarQuery(someMongoThing);

var car = getCarQuery.Query(aKey);

car.Should().Be(mockCarDocument);
}
}
}

您将如何测试所提供的代码?如果在 SomeMongoThing 之间进行抽象和GetCarQuery帮助我们接受建议。这个想法是,查询了解 MongoDb 的知识,以便能够利用 MongoDb 客户端的功能,并且查询的用户不必关心。

最佳答案

在我看来,这似乎是 XY problem 的一部分的抽象漏洞。 .

来自评论

No matter how you abstract some part of your code will handle MongoCollection, how do you test that class?

我不会测试那个类。最终包装集合的类不需要进行单元测试,因为它只是第三方关注点的包装器。 MongoCollection 的开发人员将测试他们的代码以供发布。我将整个 mongo 依赖视为第 3 方实现问题。

看看下面的替代设计

public interface ICarRepository {
IEnumerable<CarDocument> GetCars(Expression<Func<CarDocument, bool>> filter = null);
}

public class CarRepository : ICarRepository {
private readonly IMongoDatabase database;

public CarRepository(Options options) {
var client = new MongoClient(options.ConnectionString);
database = client.GetDatabase(options.DatabaseName);
}

public IEnumerable<CarDocument> GetCars(Expression<Func<CarDocument, bool>> filter = null) {
IMongoCollection<CarDocument> cars = database.GetCollection<CarDocument>(options.CollectionName);
return filter == null ? cars.AsQueryable() : (IEnumerable<CarDocument>)cars.Find(filter).ToList();
}
}

为了简单起见,我重命名了一些依赖项。它应该是不言自明的。所有与 Mongo 相关的关注点都封装在它自己的关注点中。该存储库可以根据需要利用 MongoDb 客户端的所有功能,而不会泄露对第 3 方问题的不必要依赖。

依赖的查询类可以进行相应的重构

public class GetCarQuery {
private readonly ICarRepository repository;

public GetCarQuery(ICarRepository repository) {
this.repository = repository;
}

public CarDocument Query(string aKey) {
var match = repository.GetCars(x => x.AKey == aKey);
return match.Any()
? match.First()
: repository.GetCars(x => x.AKey == "Default").FirstOrDefault();
}
}

现在可以在隔离的单元测试中简单地模拟上述类的快乐路径

public class GetCarQueryTest {
[Test]
public void ShouldGetByApiKey() {
//Arrange
var aKey = "a-key";
var mockCarDocument = new CarDocument() {
AKey = aKey
};

var data = new List<CarDocument>() { mockCarDocument };

var repository = new Mock<ICarRepository>();

repository.Setup(_ => _.GetCars(It.IsAny<Expression<Func<CarDocument, bool>>>()))
.Returns((Expression<Func<CarDocument, bool>> filter) => {
return filter == null ? data : data.Where(filter.Compile());
});

var getCarQuery = new GetCarQuery(repository.Object);

//Act
var car = getCarQuery.Query(aKey);

//Assert
car.Should().Be(mockCarDocument);
}
}

测试实际的 Mongo 相关问题需要进行集成测试,您将连接到实际的源以确保预期的行为。

关于.net - 单元测试 MongoDB.Driver dotnet core,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54888272/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com