【问题标题】:Using JUnit @ResourceLock to execute some test classes sequentially使用JUnit @ResourceLock 顺序执行一些测试类
【发布时间】:2019-07-17 00:33:28
【问题描述】:

我有一个大型集成测试套件,测试类是并行执行的,类方法是顺序执行的。有 2 个测试类使用相同的服务来创建/读取/删除实体,并且共享此服务会产生竞争条件:

  1. Foo 类正在创建记录
  2. 班级栏正在删除所有记录
  3. Foo 类试图读取创建的记录,断言它存在,但此时它已被 Bar 删除。

我尝试使用 JUnit 的 @ResourceLock 注释这两个类,但没有成功,也许我遗漏了什么?

例子:

@ResourceLock("serivceResource")
class Foo {
@Test
void fooTest(){
//create a record
//read the created record
//assert record created
}
}



@ResourceLock("serivceResource")
class Bar {
@Test
void barTest(){
//wipe all records
}
}

Foo#fooTestBar#barTest 处于竞争状态,对 @ResourceLock 的使用存在争议。

我想知道我是否需要以某种方式配置 JUnit 才能使其工作?

【问题讨论】:

  • 你如何使用@ResourceLock?有代码吗?
  • @QingfeiYuan 我只是注释了这两个类,它将与资源键参数相同的字符串传递给注释
  • 我认为 ResourceLock 注释使用 Object... 而不是字符串的值。 “serviceResource”和“serviceResource”是 2 个不同的对象,因此 ResourceLocks 不会互相阻塞。您需要创建静态字符串并为每个锁引用它

标签: java junit5


【解决方案1】:

我尝试重现并发现下面的测试在有和没有资源锁定的情况下都能正常工作

@ResourceLock("serivceResource")
class Foo {
    @BeforeAll static void beforeAll() { call("Foo.beforeAll");}
    @BeforeEach void beforeEach() { call("Foo.beforeEach");}
    @AfterAll static void afterAll() { call("Foo.afterAll");}
    @AfterEach void afterEach() { call("Foo.afterEach");}
    @Test void test1(){ call("Foo.test1");}
    @Test void test2(){ call("Foo.test2");}
    @Test void test3(){ call("Foo.test3");}

    private static void call(String action) {
        System.out.println("Enter "+action);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Leave "+action);
    }
}

@ResourceLock("serivceResource")
class Bar {

    @BeforeAll static void beforeAll() { call("Bar.beforeAll");}
    @BeforeEach void beforeEach() { call("Bar.beforeEach");}
    @AfterAll static void afterAll() { call("Bar.afterAll");}
    @AfterEach void afterEach() { call("Bar.afterEach");}
    @Test void test1(){ call("Bar.test1");}
    @Test void test2(){ call("Bar.test2");}
    @Test void test3(){ call("Bar.test3");}

    private static void call(String action) {
        System.out.println("Enter "+action);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Leave "+action);
    }
}

如果设置了资源锁则输出 - 一切都被序列化了

Enter Bar.beforeAll
Leave Bar.beforeAll
Enter Bar.beforeEach
Leave Bar.beforeEach
Enter Bar.test1
Leave Bar.test1
Enter Bar.afterEach
Leave Bar.afterEach
Enter Bar.beforeEach
Leave Bar.beforeEach
Enter Bar.test2
Leave Bar.test2
Enter Bar.afterEach
Leave Bar.afterEach
Enter Bar.beforeEach
Leave Bar.beforeEach
Enter Bar.test3    
Leave Bar.test3
Enter Bar.afterEach
Leave Bar.afterEach
Enter Bar.afterAll
Leave Bar.afterAll
Enter Foo.beforeAll
Leave Foo.beforeAll
Enter Foo.beforeEach
Leave Foo.beforeEach
Enter Foo.test1
Leave Foo.test1
Enter Foo.afterEach
Leave Foo.afterEach
Enter Foo.beforeEach
Leave Foo.beforeEach
Enter Foo.test2
Leave Foo.test2
Enter Foo.afterEach
Leave Foo.afterEach
Enter Foo.beforeEach
Leave Foo.beforeEach
Enter Foo.test3
Leave Foo.test3
Enter Foo.afterEach
Leave Foo.afterEach
Enter Foo.afterAll
Leave Foo.afterAll

如果没有设置资源锁,则输出 - 一切都是并行的。 (不过,beforeAll/afterAll 看起来非常非常奇怪!)

Enter Bar.beforeEach
Enter Bar.beforeEach
Enter Bar.beforeEach
Enter Foo.beforeEach
Enter Foo.beforeEach
Enter Foo.beforeEach
Leave Foo.beforeEach
Leave Bar.beforeEach
Leave Foo.beforeEach
Leave Bar.beforeEach
Leave Foo.beforeEach
Leave Bar.beforeEach
Enter Bar.test3
Enter Foo.test1
Enter Bar.test1
Enter Foo.test3
Enter Foo.test2
Enter Bar.test2
Leave Bar.test3
Leave Bar.test1
Leave Foo.test3
Leave Foo.test1
Leave Foo.test2
Leave Bar.test2
Enter Bar.afterEach
Enter Bar.afterEach
Enter Foo.afterEach
Enter Foo.afterEach
Enter Bar.afterEach
Enter Foo.afterEach
Leave Bar.afterEach
Leave Foo.afterEach
Leave Foo.afterEach
Leave Foo.afterEach
Leave Bar.afterEach
Leave Bar.afterEach
Enter Foo.beforeAll
Enter Bar.beforeAll
Leave Foo.beforeAll
Leave Bar.beforeAll
Enter Bar.afterAll
Enter Foo.afterAll
Leave Bar.afterAll
Leave Foo.afterAll

我的猜测 - 你的 Foo 测试会干扰其他一些测试而不是 Bar

【讨论】:

  • import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.ResourceLock;
  • 嗨。我试图重现但不能,请参阅更新的答案。我的猜测 - 你的 Foo 测试会干扰其他一些测试而不是 Bar
  • 另外请注意,你在这里打错了@ResourceLock("serivceResource")(服务与服务),所以如果其他一些测试(不是 Foo 或 Bar)引用没有错字的锁,它可能会导致问题。
猜你喜欢
  • 2018-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
  • 2013-08-16
  • 2014-09-23
  • 1970-01-01
相关资源
最近更新 更多