11

我的应用程序和 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;
    }

其中: 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 => f.GetCollection(MongoCollections.Settings)).Returns(collection.Object);

该错误指的是 MongoCollection 对象。我不认为它有一个构造函数。

我该怎么做才能让我的测试运行?

4

2 回答 2

7

这个问题很可能与:如何模拟 MongoDB 对象来测试我的数据模型?

无论如何,这是模拟所需的最小起订量配置

        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 的任何内部工作发生变化时,这可能没有用。

于 2013-03-20T20:12:52.697 回答
5

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

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
}
于 2012-11-06T18:48:14.867 回答