在 Junit5 中并行运行的多个测试之间共享类的实例

问题描述 投票:0回答:1

我正在为一个由多个 API 组成的项目开发一个测试框架。对于每个人,我都有一个不同的客户端,需要使用不同的令牌进行授权。测试是并行运行的。

我的解决方案是创建一个在映射中保存令牌的类,将客户端映射到他/她的不同服务的令牌。

public class TokenManager {
    private static final Map<Client, Map<String, Token>> tokens = new EnumMap<>(Client.class);
    
    public static String getToken(Client client, String service) {
        if (isTokenExpired(client, service)) {
            renewToken(client, service);
        }
        return tokens.get(client).get(service).getAccessToken();
}

...并在每个测试都扩展的基类的 @BeforeEach 方法中调用

getToken()
,就像这样

class BaseTest {
    
    @BeforeEach
    void setUp() {
        TokenManager.getToken(clientFoo, serviceBar);
    }
}
class SomeTestClass extends BaseTest {
    
   @Override
   void setUp() {
        super.setUp();
        // test-specific setup
    }

    @Test
    void someTest() {
        assertTrue(true);
    }

    @Test
    void otherTest() {
        assertTrue(false);
    }

我的假设是,在运行所有测试之前(通过 maven 或 Intellij runner)创建一次 TokenManager 类的实例。实际上,它是为每个测试类创建的。因此,令牌在同一类的不同测试之间共享,但在不同类的测试之间则不共享。如前所述,测试是并行运行的。

我的问题是:

  1. 当我希望 TokenManager 的实例创建一次并为所有测试提供正确的令牌时,每个测试类都会创建新令牌,这些令牌仅在过期时刷新

  2. 偶尔我会收到 NullPointerException 指出:

    java.lang.NullPointerException: Cannot invoke "Token.getAccessToken()" because the return value of "java.util.Map.get(Object)" is null
     at TokenManager.getToken(TokenManager.java:57)
     at BaseTest.setUp(BaseTest.java:9)
     at SomeTest.setUp(SomeTest.java:37)
    

我的问题是:

  1. 我应该怎么做才能强制 Junit 在不同的测试类之间共享 TokenManager 类的实例?

  2. 这个问题有更好的解决办法吗?

java junit5
1个回答
0
投票

只需将 @Synchronized 添加到 getToken 方法即可解决我的问题。因此,正如 @rzwitserloot 指出的那样,这是一个并发问题......而且只是并发问题 - TokenManager 的实例确实在所有测试之前创建一次(不是 @BeforeAll,而是“在任何之前”),并且在所有测试之间共享测试班。

© www.soinside.com 2019 - 2024. All rights reserved.