protected Pair<String, String> assertClientOK(final OAuthRegisteredService service,
                                                  final boolean refreshToken,
                                                  final String scopes) throws Throwable {
        val principal = createPrincipal();
        val code = addCode(principal, service,
            org.springframework.util.StringUtils.commaDelimitedListToSet(scopes));
        LOGGER.debug("Added code [{}] for principal [{}]", code, principal);

        val mockRequest = new MockHttpServletRequest(HttpMethod.GET.name(), CONTEXT + OAuth20Constants.ACCESS_TOKEN_URL);
        mockRequest.setParameter(OAuth20Constants.REDIRECT_URI, REDIRECT_URI);
        mockRequest.setParameter(OAuth20Constants.GRANT_TYPE, OAuth20GrantTypes.AUTHORIZATION_CODE.name().toLowerCase(Locale.ENGLISH));
        val auth = service.getClientId() + ':' + service.getClientSecret();
        val value = EncodingUtils.encodeBase64(auth.getBytes(StandardCharsets.UTF_8));
        val header = HttpConstants.BASIC_HEADER_PREFIX + value;
        mockRequest.addHeader(HttpConstants.AUTHORIZATION_HEADER, header);
        LOGGER.debug("Created header [{}] for client id [{}]", header, service.getClientId());
        mockRequest.setParameter(OAuth20Constants.CLIENT_ID, service.getClientId());
        mockRequest.setParameter(OAuth20Constants.CLIENT_SECRET, CLIENT_SECRET);

        if (StringUtils.isNotBlank(scopes)) {
            mockRequest.setParameter(OAuth20Constants.SCOPE, scopes);
        }

        mockRequest.setParameter(OAuth20Constants.CODE, code.getId());
        val mockResponse = new MockHttpServletResponse();

        LOGGER.debug("Invoking authentication interceptor...");
        requiresAuthenticationInterceptor.preHandle(mockRequest, mockResponse, null);

        LOGGER.debug("Submitting access token request...");
        val mv = accessTokenController.handleRequest(mockRequest, mockResponse);
        assertNull(this.ticketRegistry.getTicket(code.getId()));
        assertEquals(HttpStatus.SC_OK, mockResponse.getStatus());

        var refreshTokenId = StringUtils.EMPTY;
        val model = mv.getModel();
        assertTrue(model.containsKey(OAuth20Constants.ACCESS_TOKEN));

        if (refreshToken) {
            assertTrue(model.containsKey(OAuth20Constants.REFRESH_TOKEN));
            refreshTokenId = model.get(OAuth20Constants.REFRESH_TOKEN).toString();
        }
        assertTrue(model.containsKey(OAuth20Constants.EXPIRES_IN));
        val accessTokenId = extractAccessTokenFrom(model.get(OAuth20Constants.ACCESS_TOKEN).toString());

        val accessToken = this.ticketRegistry.getTicket(accessTokenId, OAuth20AccessToken.class);
        assertEquals(principal, accessToken.getAuthentication().getPrincipal());

        val timeLeft = Integer.parseInt(model.get(OAuth20Constants.EXPIRES_IN).toString());
        assertTrue(timeLeft >= TIMEOUT - 10 - DELTA);

        return Pair.of(accessTokenId, refreshTokenId);
    }
This is {@link AbstractOAuth20Tests}.

@author Misagh Moayyed
@since 5.0.0
support/cas-server-support-oauth/src/test/java/org/apereo/cas/AbstractOAuth20Tests.java