【问题标题】: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 内存数据库中的数据。但是由于某种原因,控制器方法中没有返回数据。

我尝试过的事情

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

任何帮助将不胜感激!

【问题讨论】:

    标签: java playframework playframework-1.x


    【解决方案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);
        }
    
    }
    

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

    【讨论】:

      猜你喜欢
      • 2011-08-27
      • 1970-01-01
      • 1970-01-01
      • 2018-09-25
      • 2020-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多