【问题标题】:Eventual Consistency and Test Cases最终一致性和测试用例
【发布时间】:2012-01-03 15:08:24
【问题描述】:

在使用 MongoDB 等最终一致的数据存储时,编写测试用例的最佳做法是什么?

我当前的设置是 Mongodb,具有 3 节点主/从/从设置,slave-ok 设置为 true。这意味着主节点用于只写,两个从节点用于只读。

slave 上的数据一致所需的时间相对较短,并且取决于操作和数据大小。例如,删除操作约为 3 毫秒,批量插入 1000 个对象约为 200 毫秒。

我的目标是测试我的 Dao 上的操作。它们可能是简单的 getById、delete、insert 或复杂的 findByExample。我需要验证它们是否正常工作,最终与某个超时限制一致是可以接受的。

这是我目前用来测试删除操作的,例如:

  @Test
  public void deleteTest() throws InstantiationException,
              IllegalAccessException {
        MyObject obj = new MyObject();
        obj.setName("test object");
        obj.save(obj);
        MyObject found = dao.findById(obj.getId());
        logger.info ("before: " + found);
        Assert.assertEquals(obj, found);

        dao.delete(obj.getId());
        MyObject deleted = null;
        long start = System.nanoTime();
        do {
              //TBD: need to add escape condition/timeout, else may be infinite loop....
              deleted = dao.findById(obj.getId());
              logger.info ("While: " + deleted);
        } while (deleted!=null);
        logger.info("It took " + ((System.nanoTime()-start)/1000000.00) + " ms for delete to be consistent");
        Assert.assertEquals(null, d1);
  } 

【问题讨论】:

  • 你想测试什么?您的应用程序如何处理“陈旧”数据?或者您的 MongoDB 安装需要多长时间才能传播更改?
  • 我正在尝试测试我的 Dao 上的操作。它们可能是简单的 getById、delete、insert 或复杂的 findByExample。我需要验证它们是否正常工作,最终与某个超时限制一致是可以接受的。
  • 在这种情况下,在查询从属设备之前让它们休眠到可接受的限制(如果时间过长,让它们每隔一秒左右醒来一次)。
  • 嗯,我实际上不知道可接受的限制是多少,随着添加更多节点,这可能会改变......因此我想我的次要目标也是收集时间信息。

标签: mongodb unit-testing nosql


【解决方案1】:

我想到了一些想法

  1. 在生产中,如果您已准备好从从属设备,您将永远不知道您是否获得了最新数据。这是 MongoDB 中读取从属设备的权衡。我的经验是,在正常工作条件下,奴隶是最新的。如果您必须获取最新数据,请查询主数据。
  2. 我肯定会开始使用mms 来跟踪您的副本滞后。这将告诉您您的奴隶落后多远,以便您了解数据可用的速度
  3. 至于原始测试问题,这取决于您的目标。无论是副本还是独立的,您的 DAO 都应该能够读取和写入相同的内容。您只需要确保您的应用程序了解它查询的数据可能不是最新数据。

【讨论】:

    【解决方案2】:

    对于您正在做的事情,您可以依靠这样一个事实,即使用副本集,mongo 将始终写入主服务器。所以我会把删除测试改成这样:

    /*
     * get this from the DAO,
     * or use the instance injected into the DAO, etc.
     */
    DBCollection collection = something();
    DBCursor itemsRemaining = collection.find(); //find everything
    itemsRemaining.setReadPreference(ReadPreference.PRIMARY); //force query to the master
    Assert.assertEquals(0, itemsRemaining.count());
    

    直接通过 DBCollection 进行测试允许您强制测试查询使用 master。我将测试 findById(anyOldId) 当项目不在单独测试的集合中时将返回 null。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-19
      • 1970-01-01
      • 2023-03-10
      相关资源
      最近更新 更多