如何模拟 IMongoDatabase
How to Mock IMongoDatabase
我正在使用 Moq 在 ASP.NET 核心项目中模拟我的对象。
我想模拟以下 IsConnection() 方法:
public Client(IMongoClient client)
{
_client = client;
}
public async Task<bool> IsConectionOk()
{
var pingCommand = new BsonDocument("ping", 1);
var mongoDb = _client.GetDatabase("Name");
var commandResult = await mongoDb.RunCommandAsync<BsonDocument>(pingCommand);
return commandResult != null;
}
如您所见,只有一个注入,IMongoClient
,所以我需要模拟这个。现在,我还需要模拟 IMongoDatabase
,因为 _client.GetDatabase
return 是我运行 RunCommandAsync
的 IMongoDatabase
这是我的单元测试:
[Fact]
public async Task IsConnectionOk_xxx_RunPing1Command()
{
var dbMock = new Mock<IMongoDatabase>();
var resultCommand = new BsonDocument("ok", 1);
dbMock.Setup(stub => stub.RunCommandAsync<BsonDocument>(It.IsAny<BsonDocument>(), It.IsAny<ReadPreference>(), It.IsAny<CancellationToken>())).ReturnsAsync(resultCommand);
var mongoClientMock = new Mock<IMongoClient>();
mongoClientMock.Setup(stub => stub.GetDatabase(It.IsAny<string>(), It.IsAny<MongoDatabaseSettings>())).Returns(dbMock.Object);
var client = new Client(mongoClientMock.Object);
var pingCommand = new BsonDocument("ping", 1);
//act
await client.IsConectionOk();
//assert
dbMock.Verify(mock => mock.RunCommandAsync<BsonDocument>( It.Is<BsonDocument>(x => x.Equals(pingCommand)) , It.IsAny<ReadPreference>() ,It.IsAny<CancellationToken>()));
}
你可以看到我模拟了一个 IMongoDatabase
所以我的 mongoClientMock
可以在代码执行时 return 它。当代码为 运行 时,我检查过 mongoClientMock.GetDatabase()
正在 returning a MongoDatabase
(直到那里都很好), 问题 是当 MongoDatabaseMock
调用 RunCommandAsync 时不是 return 我设置的,它只是 returns null.我不知道我在这里可能会遗漏什么,有什么想法吗?
刚发现我的问题,看看下一行:
dbMock.Setup(stub => stub.RunCommandAsync<BsonDocument>(It.IsAny<BsonDocument>(), It.IsAny<ReadPreference>(), It.IsAny<CancellationToken>())).ReturnsAsync(resultCommand);
原来 RunCommandAsync
第一个参数是 Command<TResult>
所以我需要的修复是:
dbMock.Setup(stub => stub.RunCommandAsync<BsonDocument>(It.IsAny<Command<BsonDocument>>(), It.IsAny<ReadPreference>(), It.IsAny<CancellationToken>())).ReturnsAsync(anyResultCommand);
问题解决了!
这里的事情有点棘手。
先介绍一些背景知识。
根据文档,IMongoDatabase.RunCommandAsync<TResult>
定义为
Task<TResult> RunCommandAsync<TResult>(
Command<TResult> command,
ReadPreference readPreference = null,
CancellationToken cancellationToken = null
)
注意 Command<TResult>
,而在您的代码中您传递了 BsonDocument
。
幸运的是 BsonDocument
有一个从 BsonDocument
到 Command<TResult>
的隐式转换运算符
当安装程序未获得配置的内容时,它往往 return 为空。因此,您需要确保它的设置正确,以便它执行预期的行为。
[TestClass]
public class UnitTest1 {
[TestMethod]
public async Task _IsConnectionOk_xxx_RunPing1Command() {
var dbMock = new Mock<IMongoDatabase>();
var resultCommand = new BsonDocument("ok", 1);
dbMock
.Setup(stub => stub.RunCommandAsync<BsonDocument>(It.IsAny<Command<BsonDocument>>(), It.IsAny<ReadPreference>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(resultCommand)
.Verifiable();
var mongoClientMock = new Mock<IMongoClient>();
mongoClientMock
.Setup(stub => stub.GetDatabase(It.IsAny<string>(), It.IsAny<MongoDatabaseSettings>()))
.Returns(dbMock.Object);
var client = new Client(mongoClientMock.Object);
var pingCommand = new BsonDocument("ping", 1);
//act
var actual = await client.IsConectionOk();
//assert
Assert.IsTrue(actual);
dbMock.Verify();
}
}
我正在使用 Moq 在 ASP.NET 核心项目中模拟我的对象。
我想模拟以下 IsConnection() 方法:
public Client(IMongoClient client)
{
_client = client;
}
public async Task<bool> IsConectionOk()
{
var pingCommand = new BsonDocument("ping", 1);
var mongoDb = _client.GetDatabase("Name");
var commandResult = await mongoDb.RunCommandAsync<BsonDocument>(pingCommand);
return commandResult != null;
}
如您所见,只有一个注入,IMongoClient
,所以我需要模拟这个。现在,我还需要模拟 IMongoDatabase
,因为 _client.GetDatabase
return 是我运行 RunCommandAsync
IMongoDatabase
这是我的单元测试:
[Fact]
public async Task IsConnectionOk_xxx_RunPing1Command()
{
var dbMock = new Mock<IMongoDatabase>();
var resultCommand = new BsonDocument("ok", 1);
dbMock.Setup(stub => stub.RunCommandAsync<BsonDocument>(It.IsAny<BsonDocument>(), It.IsAny<ReadPreference>(), It.IsAny<CancellationToken>())).ReturnsAsync(resultCommand);
var mongoClientMock = new Mock<IMongoClient>();
mongoClientMock.Setup(stub => stub.GetDatabase(It.IsAny<string>(), It.IsAny<MongoDatabaseSettings>())).Returns(dbMock.Object);
var client = new Client(mongoClientMock.Object);
var pingCommand = new BsonDocument("ping", 1);
//act
await client.IsConectionOk();
//assert
dbMock.Verify(mock => mock.RunCommandAsync<BsonDocument>( It.Is<BsonDocument>(x => x.Equals(pingCommand)) , It.IsAny<ReadPreference>() ,It.IsAny<CancellationToken>()));
}
你可以看到我模拟了一个 IMongoDatabase
所以我的 mongoClientMock
可以在代码执行时 return 它。当代码为 运行 时,我检查过 mongoClientMock.GetDatabase()
正在 returning a MongoDatabase
(直到那里都很好), 问题 是当 MongoDatabaseMock
调用 RunCommandAsync 时不是 return 我设置的,它只是 returns null.我不知道我在这里可能会遗漏什么,有什么想法吗?
刚发现我的问题,看看下一行:
dbMock.Setup(stub => stub.RunCommandAsync<BsonDocument>(It.IsAny<BsonDocument>(), It.IsAny<ReadPreference>(), It.IsAny<CancellationToken>())).ReturnsAsync(resultCommand);
原来 RunCommandAsync
第一个参数是 Command<TResult>
所以我需要的修复是:
dbMock.Setup(stub => stub.RunCommandAsync<BsonDocument>(It.IsAny<Command<BsonDocument>>(), It.IsAny<ReadPreference>(), It.IsAny<CancellationToken>())).ReturnsAsync(anyResultCommand);
问题解决了!
这里的事情有点棘手。
先介绍一些背景知识。
根据文档,IMongoDatabase.RunCommandAsync<TResult>
定义为
Task<TResult> RunCommandAsync<TResult>(
Command<TResult> command,
ReadPreference readPreference = null,
CancellationToken cancellationToken = null
)
注意 Command<TResult>
,而在您的代码中您传递了 BsonDocument
。
幸运的是 BsonDocument
有一个从 BsonDocument
到 Command<TResult>
当安装程序未获得配置的内容时,它往往 return 为空。因此,您需要确保它的设置正确,以便它执行预期的行为。
[TestClass]
public class UnitTest1 {
[TestMethod]
public async Task _IsConnectionOk_xxx_RunPing1Command() {
var dbMock = new Mock<IMongoDatabase>();
var resultCommand = new BsonDocument("ok", 1);
dbMock
.Setup(stub => stub.RunCommandAsync<BsonDocument>(It.IsAny<Command<BsonDocument>>(), It.IsAny<ReadPreference>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(resultCommand)
.Verifiable();
var mongoClientMock = new Mock<IMongoClient>();
mongoClientMock
.Setup(stub => stub.GetDatabase(It.IsAny<string>(), It.IsAny<MongoDatabaseSettings>()))
.Returns(dbMock.Object);
var client = new Client(mongoClientMock.Object);
var pingCommand = new BsonDocument("ping", 1);
//act
var actual = await client.IsConectionOk();
//assert
Assert.IsTrue(actual);
dbMock.Verify();
}
}