我如何使用moq来测试MongoDB服务层?

时间:2012-11-06 18:36:32

标签: c# mongodb moq

我的应用和mongo数据库之间有一个服务层。

我正在尝试使用moq构建单元测试 我对moq很新,所以我从我认为是一个微不足道的测试开始。

要测试的代码:

    public List<BsonDocument> GetAllSettings()
    {
        var collection = MongoDatabase.GetCollection<BsonDocument>("Settings");
        var query = from e in collection.AsQueryable()
                    select e;

        var settings = query.ToList();
        return settings;
    }

其中: 设置是一个集合 MongoDatabase是MongoDBDriver.MongoDatabase

我试过这个作为我的测试:

    [Test()]
    public void GetAllSettingsTest()
    {
        //Arrange
        BsonDocument doc01 = new BsonDocument();
        BsonDocument doc02 = new BsonDocument();

        var mongoDatabase = new Mock<MongoDatabase>();
        var collection = new Mock<MongoCollection<BsonDocument>>();
        mongoDatabase.Setup(f => f.GetCollection(MongoCollection.Settings)).Returns(collection.Object);
        collection.Object.Insert(doc01);
        collection.Object.Insert(doc02);

        ILogger logger = new Logger();
        DatabaseClient.DatabaseClient target = new DatabaseClient.DatabaseClient(logger);
        target.MongoDatabase = mongoDatabase.Object;

        MongoCursor<BsonDocument> cursor = collection.Object.FindAllAs<BsonDocument>();

        List<BsonDocument> expected = cursor.ToList();
        List<BsonDocument> actual;

        //Act
        actual = target.GetAllSettings();

        //Assert
        Assert.AreEqual(expected, actual);
    }

我收到了“无法找到无参数构造函数”的错误:

mongoDatabase.Setup(f =&gt; f.GetCollection(MongoCollections.Settings))。返回(collection.Object);

错误是指MongoCollection对象。我认为它没有构造函数。

我可以做些什么来让我的测试运行?

2 个答案:

答案 0 :(得分:7)

这个问题很可能与:How do I mock MongoDB objects to test my data models?

有关

无论如何,这里是模拟

所需的最小Moq配置
        var message = string.Empty;

        var serverSettings = new MongoServerSettings()
        {
            GuidRepresentation = MongoDB.Bson.GuidRepresentation.Standard,
            ReadEncoding = new UTF8Encoding(),
            ReadPreference = new ReadPreference(),
            WriteConcern = new WriteConcern(),
            WriteEncoding = new UTF8Encoding()
        };

        var server = new Mock<MongoServer>(serverSettings);
        server.Setup(s => s.Settings).Returns(serverSettings);
        server.Setup(s => s.IsDatabaseNameValid(It.IsAny<string>(), out message)).Returns(true);

        var databaseSettings = new MongoDatabaseSettings()
        {
            GuidRepresentation = MongoDB.Bson.GuidRepresentation.Standard,
            ReadEncoding = new UTF8Encoding(),
            ReadPreference = new ReadPreference(),
            WriteConcern = new WriteConcern(),
            WriteEncoding = new UTF8Encoding()
        };

        var database = new Mock<MongoDatabase>(server.Object, "test", databaseSettings);
        database.Setup(db => db.Settings).Returns(databaseSettings);
        database.Setup(db => db.IsCollectionNameValid(It.IsAny<string>(), out message)).Returns(true);

        var mockedCollection = collection.Object;

无论如何,正如我在链接问题中所提到的,当MongoDriver的任何内部工作发生变化时,这可能没有用。

答案 1 :(得分:4)

我不熟悉MongoDbDriver.MongoDatabase,但如果它像我认为的那样工作,那么你就不能直接嘲笑它。您需要抽象MongoDB访问代码,并模拟它。这将是一个实际的单元测试。 e.g。

public interface IMongoDBRepository
{
   Collection<T> GetCollection<T>(string name) where T BsonDocument;
}

public class MongoDbRepository : IMongoDBRepository
{
   public Collection<T> GetCollection<T>(string name) 
     where T : BsonDocument
   {
      return MongoDatabase.GetCollection<BsonDocument>(name);
   }
}

现在,在你的代码中,你注入一个IMongoDBRepository(使用你喜欢的任何DI方法),你的代码看起来像这样:

private IMongoDBRepository _mongoDBRepository; //this gets injected
public List<BsonDocument> GetAllSettings()
{
    var collection = _mongoDBRepository.GetCollection<BsonDocument>("Settings");
    var query = from e in collection.AsQueryable()
                select e;

    var settings = query.ToList();
    return settings;
}

最后你的单元测试:

[Test()]
public void GetAllSettingsTest()
{
    //Arrange
    BsonDocument doc01 = new BsonDocument();
    BsonDocument doc02 = new BsonDocument();

    var mongoDatabase = new Mock<IMongoDBRepository>();
    var collection = new Mock<MongoCollection<BsonDocument>>();
    mongoDatabase.Setup(f => f.GetCollection(MongoCollection.Settings)).Returns(collection.Object);
    collection.Object.Insert(doc01);
    collection.Object.Insert(doc02);

   //rest of test
}