玩!框架功能测试幽灵数据

Posted

技术标签:

【中文标题】玩!框架功能测试幽灵数据【英文标题】:Play! Framework Functional Test ghost data 【发布时间】:2021-03-03 23:10:12 【问题描述】:

希望其他人和我有同样的问题,或者有其他想法。

我目前正在运行 Play 1.4.x(不是选择),但也在努力升级到 Play 1.5.x,尽管我证实两个版本都发生了同样的问题。 我创建了一个简单的功能测试,通过夹具加载数据

我的加载测试数据的夹具是这样的

data.yml

User(testUser):
  name: blah

AccessToken(accessToken):
 user: testUser
 token: foo


Data(testData):
 user: testUser
 ...
   

我创建了一个控制器来处理这样的数据,它具有用于身份验证检查的中间件。路由文件会将/foo 之类的内容映射到BasicController.test

public class BasicController extends Controller


  @Before
  public void doAuth()
    String token = "foo"; // Get token somehow from header

    AccessToken token = AccessToken.find("token = ?", token).first(); // returns null;
    // do something with the token


    if(token == null)
     //return 401
    

    //continue to test()
  


  public void test()
     User user = //assured to be logged-in user
     ... // other stuff not important
  


最后我的功能测试是这样的:

 public class BasicControllerTest extends FunctionalTest

   @org.junit.Before
   public void loadFixtures()
       Fixtures.loadModels("data.yml");
   

   
   @Test
   public void doTest()
      Http.Request request = newRequest()
      request.headers.put(...); // Add auth token to header
      Http.Response response = GET(request, "/foo");
      assertIsOk(response);
   

 

现在,我遇到的问题是,我可以验证令牌在标头中仍然可见,但运行 AccessToken token = AccessToken.find("token = ?", token).first(); 返回 null

我在功能测试中验证,在调用GET 方法之前,通过加载夹具成功创建了accessToken 和用户。通过在 1.5.x 中播放新的 DBBrowser 插件,我可以看到我的 H2 内存数据库中的数据。但是由于某种原因,控制器方法中没有返回数据。

我尝试过的事情

    确保仅加载一次固定装置,因此不会出现在读取数据时清除数据的竞争条件。 使用多种方式查询数据库,通过nativeQueryjpql/hql query language和通过播放原生方式查询数据。 测试不同版本的 play

任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

此问题发生在功能测试中,因为 JPA 事务必须封装在作业中,以确保事务的结果在您的方法中可见。否则,由于整个功能测试在事务中运行,结果将仅在测试结束时可见(类似情况请参阅how to setup database/fixture for functional tests in playframework)。

所以你可以试试这个:

@Test
public void doTest() 
    ...
    AccessToken token = new Job<AccessToken>() 
        @Override
        public User doJobWithResult() throws Exception 
            return AccessToken.find("token = ?", tokenId).first();
        
    .now().get();
    ....


希望它有效!

【讨论】:

嘿汤姆!感谢您尝试一下!不幸的是,我的问题不在于功能测试中没有加载数据。这是它在功能测试中加载,但由于某种原因没有加载到控制器中。够奇怪的。 何,误会请见谅。您可以尝试在您的 doAuth() 方法中调用“AccessToken.findAll()”来检查您的数据库中可以找到什么吗?您是否也尝试在 yml 配置中使用引号,例如 token: "foo" ? 此外,FunctionalTest 具有隔离事务,因此您可以尝试在我之前描述的作业中调用 Fixtures.loadModels("data.yml") 以确保新插入的数据在测试之外可见,因此也可用于您的控制器。【参考方案2】:

我想我有类似的问题,也许这对某人有帮助。

功能测试有一个事务,控制器有一个不同的事务。只有在提交了这些更改的情况下,测试中所做的更改才会对任何进一步的事务可见。

可以通过像这样在功能测试中关闭和重新打开事务来实现这一点。

// Load / Persist date here

JPA.em().getTransaction().commit(); // commit and close the transaction
JPA.em().getTransaction().begin();  // reopen (if you need it)

现在应该在控制器方法中返回数据。

所以你的测试应该是这样的:

public class BasicControllerTest extends FunctionalTest

    @org.junit.Before
    public void loadFixtures()
        Fixtures.loadModels("data.yml");
        JPA.em().getTransaction().commit();
        // JPA.em().getTransaction().begin();   reopen (if you need it)
    

   
    @Test
    public void doTest()
        Http.Request request = newRequest()
        request.headers.put(...); // Add auth token to header
        Http.Response response = GET(request, "/foo");
        assertIsOk(response);
    


我从来没有用固定装置尝试过这个。但我会假设它们在同一个事务中运行。

【讨论】:

以上是关于玩!框架功能测试幽灵数据的主要内容,如果未能解决你的问题,请参考以下文章

玩!框架 1.2.5:如何测试响应是不是安全?

QQ飞车里的宠物小灰灰、闪电幽灵razor和冰蝠影,哪一个有宠物加成?还有这三个宠物的技能,请介绍一下

提升自动化效率,一起玩转Selenium框架

玩 2.4.6,配置测试中字节码增强的构建设置

幽灵按键

幽灵按钮的实现