如何模拟 IMongoDatabase

mon*_*Bug 5 c# unit-testing moq mongodb

我正在使用 Moq 来模拟 ASP.NET Core 项目中的对象。

我想模拟以下 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;        
}
Run Code Online (Sandbox Code Playgroud)

如您所见,只有一次注入,IMongoClient所以我需要模拟这一注入。IMongoDatabase现在,我还需要模拟,因为_client.GetDatabase返回给我一个IMongoDatabase运行的RunCommandAsync

这是我的单元测试:

[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>()));
}
Run Code Online (Sandbox Code Playgroud)

您可以看到我模拟了 a,IMongoDatabase以便mongoClientMock在代码执行时可以返回它。当代码运行时,我检查了是否mongoClientMock.GetDatabase()返回 a MongoDatabase(直到那里都很好),问题是当MongoDatabaseMock调用RunCommandAsync时没有返回我设置的内容,它只是返回null。我不知道我在这里可能会错过什么,有什么想法吗?

Nko*_*osi 4

事情有点棘手。

首先介绍一些背景。

根据文档,IMongoDatabase.RunCommandAsync<TResult>定义为

Task<TResult> RunCommandAsync<TResult>(
    Command<TResult> command,
    ReadPreference readPreference = null,
    CancellationToken cancellationToken = null
)
Run Code Online (Sandbox Code Playgroud)

请注意Command<TResult>,在您的代码中传递了BsonDocument.

幸运的是,有一个从到 的BsonDocument隐式转换运算符BsonDocumentCommand<TResult>

当设置未获取配置内容时,它往往会返回 null。因此,您需要确保它设置正确,以便它执行预期的行为。

[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();
    }
}
Run Code Online (Sandbox Code Playgroud)