Как издеваться над библиотекой JsonWebToken в JUnit 5 Java

#java #junit #jwt

#java #junit #jwt

Вопрос:

У меня есть служба аутентификации, которая возвращает JsonWebToken.

Сначала он проверяет предоставленный токен, считывает утверждения, а затем генерирует новый на основе этих данных.

Ниже приведен метод, который выполняет эти конкретные действия:

 @Override
    public String authenticate(String appName, String zendeskJwt) {
        String zendeskPublicKeyString = zendeskService.getAppPublicKey(appName);
        RSAPublicKey zendeskPublicKey = asymmetricKeyParser.publicKey(zendeskPublicKeyString);
        Jws<Claims> parsedZendeskJws = Jwts.parserBuilder()
                .setSigningKey(zendeskPublicKey)
                .build()
                .parseClaimsJws(zendeskJwt);

        String zendeskUserReference = parsedZendeskJws.getBody().getSubject();
        ZendeskUser zendeskUser = zendeskService.getZendeskUser(zendeskUserReference);

        Date currentTime = new Date(System.currentTimeMillis());
        Date expirationTime = new Date(currentTime.getTime()   cspExciteJwtProperties.getExpirationDuration().toMillis());

        RSAPrivateKey cspPrivateKey = asymmetricKeyParser.privateKey(cspExciteJwtProperties.getPrivateKey());

        return Jwts.builder()
                .setIssuedAt(currentTime)
                .setExpiration(expirationTime)
                .claim(CLAIM_ZENDESK_AGENT_ID, zendeskUser.getId())
                .claim(CLAIM_HYDRA_USER_ID, zendeskUser.getExternalId())
                .signWith(cspPrivateKey)
                .compact();

    }

  

Сам код работает просто отлично. Мой вопрос касается модульных тестов. Я хочу протестировать этот метод.

Я пытался проверить множество материалов, но ни один из них не сработал для меня. Согласно источникам, все говорят, что издеваться над самой библиотекой — плохая идея. Но я не совсем уверен, как я могу пройти модульный тест, не издеваясь над библиотекой Jwt. У меня есть интеграционные тесты, и это другой сценарий. Для модульных тестов я не должен делать никаких реальных запросов.

Вот что я пробовал до сих пор

    private RSAPrivateKey privateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        String parsedPrivateKey = PRIVATE_KEY
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\n", "").trim();
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        var decoded = Base64.getDecoder().decode(parsedPrivateKey);
        PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(decoded);

        return (RSAPrivateKey) keyFactory.generatePrivate(keySpecPKCS8);
    }

    private String generateJwt() throws InvalidKeySpecException, NoSuchAlgorithmException {
        RSAPrivateKey cspPrivateKey = privateKey();
        System.out.println(cspPrivateKey);
        Duration expirationDuration = Duration.parse("PT20M");
        Date currentTime = new Date(System.currentTimeMillis());
        Date expirationTime = new Date(currentTime.getTime()   expirationDuration.toMillis());

        return Jwts.builder()
                .setIssuedAt(currentTime)
                .setExpiration(expirationTime)
                .claim(CLAIM_ZENDESK_AGENT_ID, 123)
                .claim(CLAIM_HYDRA_USER_ID, "123")
                .signWith(cspPrivateKey)
                .compact();
    }

    @Test
    void authenticate() throws InvalidKeySpecException, NoSuchAlgorithmException {
        String appName = "appName";
        String zendeskJwt = generateJwt();
        RSAPublicKey zendeskPublicKey = new AsymmetricKeyParser().publicKey(PUBLIC_KEY);
        ZendeskUser zendeskUser = new ZendeskUser(123, "123");

        Jws<Claims> jws = new Jws<Claims>() {

            @Override
            public JwsHeader getHeader() {
                return null;
            }

            @Override
            public Claims getBody() {
                return null;
            }

            @SneakyThrows
            @Override
            public String getSignature() {
                return generateJwt();
            }
        };

        when(zendeskService.getAppPublicKey(appName)).thenReturn(String.valueOf(zendeskPublicKey));
        // This is how I am trying to mock JWT
        when(Jwts.parserBuilder()
                .setSigningKey(zendeskPublicKey)
                .build()
                .parseClaimsJws(zendeskJwt)).thenReturn(jws);

        when(zendeskService.getZendeskUser("//example.com")).thenReturn(zendeskUser);

        testObj.authenticate(appName, zendeskJwt);
    }
  

Это выдает мне эту ошибку

 org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
  

Любые предложения приветствуются.

Комментарии:

1. Если кому-то интересно, как я издевался над библиотекой, ну, я этого не делал. Я издевался над всем остальным, но не над самой библиотекой, поэтому я добавил предварительно сгенерированные сертификаты и ключи, чтобы заставить ее работать.