playframework: - 数据库/测试框架/缓存错误

时间:2011-08-04 16:35:10

标签: database unit-testing playframework

我已将此问题完全隔离到一个非常简单的播放应用 我认为它与一些数据库缓存有关,但我无法弄清楚

BasicTest.java 
========== 
import org.junit.*; 
import play.test.*; 
import play.Logger; 
import models.*; 
import play.mvc.Http.*; 
public class BasicTest extends FunctionalTest { 
    @Before public void setUp() { 
    Fixtures.deleteDatabase(); 
    Fixtures.loadModels("data.yml"); 
    Logger.debug("countFromSetup=%s",User.count()); 
    } 
    @Test 
    public void test() { 
    Response response= GET("/"); 
    Logger.debug("countFromTest=%s",User.count()); 
    assertIsOk(response); 
    } 
} 

Uncommented Configs 
================ 
%prod.application.mode=prod 
%test.application.mode=dev 
%test.db.url=jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0 
%test.db=mysql:root:xxx@t_db 
%test.jpa.ddl=create 
%test.mail.smtp=mock 
application.mode=dev 
application.name=test 
application.secret=jXKw4HabjhaNvosxgzq39to9BJECtOr39EXrEabsQAZKi7YoWAwQWo3B BFUOQnJw 
attachments.path=data/attachments 
date.format=yyyy-MM-dd 
db=mysql:root:xxx@db 
mail.smtp=mock 
Application.java 
============ 
package controllers; 
import play.*; 
import play.mvc.*; 
import models.*; 
public class Application extends Controller { 
    public static void index() { 
    Logger.debug("countFromIndex=%s",User.count()); 
    render(); 
    } 
} 
>play test 

Output of log after running the BasicTest http://localhost:9000/@tests 
================================================== 
11:54:59,008 DEBUG ~ countFromSetup=1 
11:54:59,021 DEBUG ~ countFromIndex=0 
11:54:59,034 DEBUG ~ countFromTest=1 
point to browser=> http://localhost:9000 
12:25:59,781 DEBUG ~ countFromIndex=1 

记录期间发生了什么?         响应响应= GET(“/”); 这个'bug'几乎使我的测试用例无用

3 个答案:

答案 0 :(得分:2)

我认为它是JUnit的默认行为,@ Before注释使方法在每次测试之前运行:

  

编写测试时,通常会发现需要进行多项测试   在运行之前创建的类似对象。诠释公共空白   使用@Before的方法会导致该方法在Test之前运行   方法。 @Before超类方法将在这些方法之前运行   当前班级。

来自:http://junit.sourceforge.net/javadoc/org/junit/Before.html

如果您希望在使用@BeforeClass注释后运行设置:http://junit.sourceforge.net/javadoc/org/junit/BeforeClass.html

答案 1 :(得分:2)

它可能与交易有关。我和Spring / JUnit夫妇一起遇到了类似的情况。

以下是测试的事务执行(我认为):

  1. 启动事务t1,
  2. 执行设置,从缓存中获取结果。
  3. 执行测试。
  4. 启动事务t2以执行控制器GET(“/”)
  5. 结果是从数据库中提取的,但由于尚未提交t1,因此不会显示。
  6. 关闭事务t2并提交t1!
  7. 关闭事务t1并提交t2!
  8. 顺便说一下,这不是真正的功能测试。对于功能测试,您不应该检查此类数据,而只检查http状态。转向UnitTests。查看功能测试的源代码时,您可以看到实现的所有检查都是针对响应/ http检查。

答案 2 :(得分:-1)

在PlayFramework中,prod有n + 1个线程,测试配置文件或编译配置文件有1个线程。因此,如果您有双核CPU,如果您在prod中运行则有3个线程,如果您使用“test”启动应用程序则有一个线程。 现在,还有一个有趣的事实:每次执行都有一个Tx。因此,当您的应用程序启动并启动您的第一个测试时,会发生以下情况:

  • 以一个帖子开始播放。
  • JUnitRunner启动,第一个测试myTest被执行。它是应用程序的HTTP连接。你看到0的原因是因为在@Before语句之前执行了Response GET。
  • @Before被执行,创建你的条目,结果计数在@Before中是准确的,因为它是在同一个Tx中完成的。

所以我建议您使用@BeforeClass,或者不是在@Before中执行设置,而是通过myTest中的直接调用来执行具有Response的非常具体的测试用例。

我认为如果你替换这段代码

@Test
public void myTest() {
    Response response= GET("/test");
}

用这个

@Test
public void myTest() {
    assertEquals(1,User.count());
}

正确吗?

所以你得到这个的原因不是错误。这只是因为我们为测试环境提供了一个线程配置。

尼古拉斯