appengine单元测试只获取10个实体

时间:2014-10-14 07:19:31

标签: java google-app-engine unit-testing junit objectify

我已经用appengine编写了一个单元测试,在填充1000之后需要获取250个实体。但是我发现大多数时候它只获取10个实体。只有极少数时间我看到它已经取得了250个。我很确定临时数据存储区确实有1000个实体,因为我在保存时打印它们。

@Before方法

中的

System.out.println( "Adding "+players.size()+ "  entries" );
ofy().save().entities(players);

按预期打印1000

@Test方法

中的

List<Player> players = ofy().load().type( Player.class ).order("-score").limit( 250 ).list();
System.out.println( "Fetched "+players.size()+" top players" );

3 个答案:

答案 0 :(得分:2)

这可能是由于测试数据存储区服务模拟了最终的一致性行为。检查未应用的作业百分比配置。

  

通过将未应用的作业百分比设置为100,我们将指示本地数据存储区以最大的最终一致性进行操作。最大的最终一致性意味着写入将提交但始终无法应用,因此全局(非祖先)查询将始终无法查看更改。这当然不能代表您的应用程序在生产中运行时将看到的最终一致性数量,但出于测试目的,能够配置本地数据存储区以使其每次都以这种方式运行非常有用。

如果有帮助,请尝试这样的事情。

@BeforeClass
public static void setUpClass() throws Exception {
    localServiceTestHelper = new LocalServiceTestHelper(
            new LocalDatastoreServiceTestConfig().setDefaultHighRepJobPolicyUnappliedJobPercentage(0));
}

但是,请注意以下事实。

  

请注意,setDefaultHighRepJobPolicyUnappliedJobPercentage(0)会将本地数据存储区服务切换为主/从模式。

您可以找到更多详情here

答案 1 :(得分:2)

虽然您可能也会遇到最终一致性问题,但您可能也没有正确划分您的请求。这将产生两种影响:您将受到会话污染,并且将不会提交挂起的异步操作。

与JPA和JDO一样,Objectify基于工作会话的想法。在正常操作中,ObjectifyFilter开始和关闭这一工作会议;每个请求可以获得一个会话,并且在会话结束时所有待处理的异步&amp;延迟操作将刷新到数据存储区。

在单元测试中,没有ObjectifyFilter,也没有隐含的请求概念。例如,任何单个测试都可以发出多个请求!如果直接测试JAX-RS方法,这种情况尤为常见;每个方法都是一个单独的请求。

因此,您需要建立此上下文。在Objectify 5.1及更高版本中,您必须明确地启动上下文。最好的方法是:

ObjectifyService.run(new VoidWork() {
    public void vrun() {
        // the code you want to execute within a single request
    }
});

您可以在测试中多次调用它来模拟多个请求。

另一方面,如果您正在编写测试,并认为每个测试都在单个请求的上下文中完全执行,则可以在@ Before / @ After方法(或@BeforeMethod)中设置和拆除该上下文/ @ AfterMethod如果使用TestNG)。请参阅静态方法ObjectifyService.begin()

这些不是互斥的选择;即使存在先前的上下文,您也可以执行run()操作;客观化的上下文就像堆栈一样。

答案 2 :(得分:0)

好的,它解决了。正如@pgiecek之前所说,它最终的一致性。我只需要修改以下代码,将立即提交的记录化为。。我回到主/从模式

ofy().save().entities(rankings).now()