Интеграционный тест JUnit выдает исключение SQLNonTransientConnectionException - PullRequest
0 голосов
/ 09 мая 2020

Проблема, я написал одну новую интеграцию. Все работают в среде docker, но после добавления этого нового тестового примера другой не работает со следующим исключением:

    Too many connections

    at org.flywaydb.core.internal.jdbc.JdbcUtils.openConnection(JdbcUtils.java:60)
    at org.flywaydb.core.internal.database.DatabaseFactory.createDatabase(DatabaseFactory.java:72)
    at org.flywaydb.core.Flyway.execute(Flyway.java:1670)
    at org.flywaydb.core.Flyway.migrate(Flyway.java:1356)
    at org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer.afterPropertiesSet(FlywayMigrationInitializer.java:66)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1821)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1758)
    ... 66 more
Caused by: java.sql.SQLNonTransientConnectionException: Too many connections
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)

Это только что добавленный тестовый пример:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = FlywayConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles({"aws", "local"})
public class BoundaryValueDeltaControllerTest {

    private static final String API_V1 = "/api/v1/";

    @Autowired
    TestRestTemplate testRestTemplate;

    @Autowired
    private DomainBuilder domainBuilder;

    @Autowired
    private AppBuilder appBuilder;

    @Autowired
    private UserBuilder userBuilder;

    @Autowired
    private DomainAdminBuilder domainAdminBuilder;

    @Autowired
    private BoundarySetBuilder boundarySetBuilder;

    @MockBean
    private LoginUserProvider loginUserProvider;

    @MockBean
    private LoginTokenService loginTokenService;

    @MockBean
    private BoundaryServiceAdapter serviceAdapter;

    @LocalServerPort
    private int port;

    LoginUserInfo loggedInUser;

    @Before
    public void setUp() {
        clear();
    }

    @After
    public void tearDown() {
        clear();
    }

    @Test
    public void updateBoundaryValuesFromApi() throws UrsBusinessException {
        Domain domain = domainBuilder.persist();
        App app = appBuilder.persist(domain);
        BoundarySet boundarySet =  boundarySetBuilder.persist(domain);
        User user = userBuilder.persist(domain.getAuthor().getUsername());
        aLoggedInUser(domain.getAuthor().getUsername());
        domainAdminBuilder.persist(user, domain);

        mockUpdateBoundaryValuesFromApiData();

        ResponseEntity<String> response = callUpdateBoundaryValuesFromApi(domain, boundarySet, app);

        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertNotNull(response.getBody());
    }

    private void mockUpdateBoundaryValuesFromApiData() throws UrsBusinessException {
        BoundaryValueInfo boundaryValueInfo = new BoundaryValueInfo();
        boundaryValueInfo.setBoundaryValueId(10L);
        boundaryValueInfo.setBoundaryValueKey("boundaryValueKey");
        boundaryValueInfo.setBoundaryValueName("boundaryValuename");

        when(serviceAdapter.readInfoFromApiUsingApp(any(), any(), any())).thenReturn(new BoundaryValueInfo[]{boundaryValueInfo});
    }

    private ResponseEntity<String> callUpdateBoundaryValuesFromApi(Domain domain, BoundarySet boundarySet, App app) {
        String url = url(API_V1 + "domains/" + domain.getName() + "/boundarysets/" + boundarySet.getBoundarySetName() + "/app/" + app.getName()+ "/updatefromapi/");
        return testRestTemplate.exchange(url,HttpMethod.GET, null, String.class);
    }

    private String url(String url) {
        return "http://localhost:" + port + url;
    }

    private void aLoggedInUser(String username) {
        Claims claims = Jwts.claims();
        claims.put("username", username);
        loggedInUser = LoginUserInfo.parse(claims);

        when(loginUserProvider.getLoggedInUser()).thenReturn(loggedInUser);
        when(loginTokenService.parseToken(any())).thenReturn(loggedInUser);
    }

    private void clear() {
        appBuilder.deleteAll();
        boundarySetBuilder.deleteAll();
        domainAdminBuilder.deleteAll();
        domainBuilder.deleteAll();
        userBuilder.deleteAll();
    }
}

И это тестовый пример, который терпит неудачу после:

@ActiveProfiles({"aws", "local"})
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UnauthorizedControllerTest {

    private static final Logger LOGGER = LoggerFactory.getLogger(UnauthorizedControllerTest.class);

    @Autowired
    private TestRestTemplate testRestTemplate;

    @LocalServerPort
    private int port;

    @Autowired
    private ApplicationContext context;

    private Map<Class<?>, List<String>> excludedMethodsPerController;

    @Before
    public void setUp() {
        excludedMethodsPerController = excludedMethodsPerController();
    }

    @Test
    public void contextStarts() {
        assertNotNull(context);
    }

    /**
     * If this test fails it probably means you forget to add the LoggedInUser annotation on a controller method.<br>
     * If you are 100% sure there is no annotation required, add the method to the list of excluded methods.
     */
    @Test
    public void controllerCall_WithoutAuthorization_ReturnsUnauthorized() {
        Map<String, Object> controllerBeans = context.getBeansWithAnnotation(Controller.class);

        for (Object controllerInstance : controllerBeans.values()) {
            LOGGER.info("Checking controller {}", controllerInstance);
            checkController(controllerInstance);
        }
    }

    public void checkController(Object controllerInstance) {
        // Use AopUtils for the case that spring wraps the controller in a proxy
        Class<?> controllerClass = AopProxyUtils.ultimateTargetClass(controllerInstance);
        Method[] allMethods = controllerClass.getDeclaredMethods();


        for (Method method : allMethods) {
            LOGGER.info("Checking method: {}", method.getName());
            if (!isCallable(controllerClass, method)) {
                continue;
            }

            String urlPrefix = urlPrefix(controllerClass);

            Mapping mapping = Mapping.of(method.getAnnotations());

            for (String url : mapping.urls) {
                for (RequestMethod requestMethod : mapping.requestMethods) {
                    ResponseEntity<String> exchange = exchange(urlPrefix + url, requestMethod);

                    String message = String.format("Failing %s.%s", controllerClass.getName(), method.getName());
                    assertEquals(message, HttpStatus.UNAUTHORIZED, exchange.getStatusCode());
                }
            }
        }
    }

    private ResponseEntity<String> exchange(String apiEndpoint, RequestMethod requestMethod) {
        return testRestTemplate.exchange(url(replacePathVariables(apiEndpoint)), HttpMethod.resolve(requestMethod.name()), null, String.class);
    }

    private String urlPrefix(Class<?> aClass) {
        if (!aClass.isAnnotationPresent(RequestMapping.class)) {
            return "";
        }

        RequestMapping annotation = aClass.getAnnotation(RequestMapping.class);
        return annotation.value()[0];
    }

    private String url(String url) {
        return "http://localhost:" + port + url;
    }

    private boolean isCallable(Class<?> controller, Method method) {
        return Modifier.isPublic(method.getModifiers())
                && !isExcluded(controller, method)
                && !isExternal(controller);
    }

    private boolean isExcluded(Class<?> controller, Method method) {
        List<String> excludedMethodsPerController = this.excludedMethodsPerController.getOrDefault(controller, new ArrayList<>());
        return excludedMethodsPerController.contains(method.getName());
    }

    private boolean isExternal(Class<?> controller) {
        return controller.getName().startsWith("org.spring");
    }

    private String replacePathVariables(String url) {
        return url.replaceAll("\\{[^\\/]+}", "someValue");
    }

    /**
     * There must be a really good reason to exclude the method from being checked.
     *
     * @return The list of urls that must not be checked by the security
     */
    private static Map<Class<?>, List<String>> excludedMethodsPerController() {
        Map<Class<?>, List<String>> methodPerController = new HashMap<>();

        methodPerController.put(AuthenticationController.class, Collections.singletonList("generateAuthorizationToken"));
        methodPerController.put(SystemUserLoginController.class, Arrays.asList("systemUserLogin", "handleException"));
        methodPerController.put(ValidationController.class, Collections.singletonList("isValid"));

        return methodPerController;
    }

    private static class Mapping {

        String[] urls;
        RequestMethod[] requestMethods;

        Mapping(String[] urls, RequestMethod[] requestMethods) {
            this.urls = urls;
            this.requestMethods = requestMethods;
        }

        Mapping(String[] urls, RequestMethod method) {
            this(urls, new RequestMethod[]{method});
        }

        static Mapping of(Annotation[] annotations) {
            for (Annotation annotation : annotations) {
                Mapping mapping = of(annotation);
                if (null != mapping) {
                    return mapping;
                }
            }

            throw new IllegalStateException("expected annotation not present");
        }

        static Mapping of(Annotation annotation) {
            if (annotation instanceof RequestMapping) {
                RequestMapping mapping = (RequestMapping) annotation;
                return new Mapping(mapping.value(), mapping.method());
            }
            if (annotation instanceof GetMapping) {
                GetMapping mapping = (GetMapping) annotation;
                return new Mapping(mapping.value(), RequestMethod.GET);
            }
            if (annotation instanceof PostMapping) {
                PostMapping mapping = (PostMapping) annotation;
                return new Mapping(mapping.value(), RequestMethod.POST);
            }
            if (annotation instanceof PutMapping) {
                PutMapping mapping = (PutMapping) annotation;
                return new Mapping(mapping.value(), RequestMethod.PUT);
            }
            if (annotation instanceof DeleteMapping) {
                DeleteMapping mapping = (DeleteMapping) annotation;
                return new Mapping(mapping.value(), RequestMethod.DELETE);
            }
            return null;
        }
    }
}

Другие тестовые примеры раньше работали нормально, но я не понимаю, что произошло после добавления нового тестового примера. Кто-нибудь может мне помочь?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...