玩!框架功能测试幽灵数据
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 内存数据库中的数据。但是由于某种原因,控制器方法中没有返回数据。
我尝试过的事情
-
确保仅加载一次固定装置,因此不会出现在读取数据时清除数据的竞争条件。
使用多种方式查询数据库,通过
nativeQuery
jpql/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);
我从来没有用固定装置尝试过这个。但我会假设它们在同一个事务中运行。
【讨论】:
以上是关于玩!框架功能测试幽灵数据的主要内容,如果未能解决你的问题,请参考以下文章