Исключение (трассировка стека) недоступно в модульном тестировании springboot

#java #spring-boot #exception #junit5

#java #весенняя загрузка #исключение #junit5

Вопрос:

Я начинаю использовать spring boot framework и спотыкаюсь на каждом втором шаге. В настоящее время у меня сложилась ситуация, которую я абсолютно не понимаю.

Я использую spring boot 2.3.5. СБОРКА РЕЛИЗА с помощью maven

     <properties>
        <java.version>11</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/>
        <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.1.6.Final</version>
        </dependency>

        <!-- OpenAPi (swagger)-->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.2.32</version>
        </dependency>

    </dependencies>
 

Я создал довольно простой класс RESTCommunication. Нет @Component, @Controller или чего-то подобного.

 public class RESTCommunication {
    private final Logger m_logger = LoggerFactory.getLogger(this.getClass());
    private String m_contentType;
    private String m_path;    
    private String m_body;

    private HashMap<String,String> m_urlParams;
    private HashMap<String,String> m_queryParams;

    public RESTCommunication() {
    m_logger.debug("RESTCommunication constructor");
        
    m_scheme    = RESTCommunication.SCHEME_DEFAULT;
    m_authority = RESTCommunication.AUTHORITY_DEFAULT;
    m_port      = RESTCommunication.PORT_DEFAULT;
    m_path      = RESTCommunication.PATH_DEFAULT;

    m_urlParams = new HashMap<>();
    // m_queryParams = new HashMap<>();  // I know that this is the reason for the exception
}

@Override
public String toString() {
    StringBuilder sbToString = new StringBuilder();
    sbToString.append(buildURI());
    sbToString.append("|numURLParams:").append(m_urlParams.size());
    sbToString.append("|numQueryParams:").append(m_queryParams.size());  // This has to fail because m_queryParams is not initialized
    return sbToString.toString();
}
    .....
 

Для этого класса я создал очень простой тестовый класс RESTCommunicationTest

 @SpringBootTest
public class RESTCommunicationTest {
    private final Logger m_logger = LoggerFactory.getLogger(this.getClass());

    @Test
    public void defaultInitTest() {
        RESTCommunication restComm = new RESTCommunication();
  
        String restCommURL = restComm.toString();  // Expect the nullpointer INSIDE the toString method
        String expectedURL = sbExpected.toString();
        
        assertEquals(expectedURL, restCommURL, "Expected URL does not match generated");
    }
    
 

Я запускаю тест с помощью команды: $./mvnw -e -X package -Dtest=RESTCommunicationTest#defaultInitTest
И, как и ожидалось, я вижу указатель Nullpointer в стандартном журнале.
НО в журнале я нахожу это:

 webServerFactoryCustomizerBeanPostProcessor
websocketServletWebServerCustomizer
welcomePageHandlerMapping
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 3.532 s <<< FAILURE! - in org.highpots.hippo.core.communication.RESTCommunicationTest
[ERROR] defaultInitTest  Time elapsed: 0.399 s  <<< ERROR!
java.lang.NullPointerException                                                                                                                                                                                                                                                    
    at org.ilovespringboot.not.RESTCommunicationTest.defaultInitTest(RESTCommunicationTest.java:36)

2020-12-08 22:18:10.810  INFO 10381 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
[INFO]
[INFO] Results:
[INFO]
[ERROR] Errors:
[ERROR]   RESTCommunicationTest.defaultInitTest:36 » NullPointer
[INFO]
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
 

Указатель null в RESTCommunicationTest.java:36. Абсолютно никаких намеков на то, что реальный указатель NullPointer происходит в классе RESTCommunication.
Может кто-нибудь объяснить мое такое поведение? Я делаю что-то не так?
Я знаю, что я какой-то динозавр программирования. (java-проектам более 10 лет в прошлом). Но я ожидал бы получить подсказку, где генерируется исключение. Я бы ожидал трассировки стека с подробными разделами, вызванными разделами.
Если вы не можете себе представить, что это ненормальное поведение. Потому что это означало бы, что я должен находить все ошибки, просматривая полный исходный код… Это невозможно

Заранее благодарю за помощь Харри Э

Ответ №1:

Maven использует плагин surefire для запуска тестов.Чтобы увидеть трассировку стека исключений, вы должны установить trimStackTrace в false в конфигурации плагина surefire.

Исторически верный плагин использовался для печати полной трассировки стека. Хотя информация в трассировке стека была полезна для отладки, трассировки стека занимали довольно много места в выводе консоли. Особенно, если было несколько неудачных тестов, стало легко потеряться в шуме.

Начиная с версии 2.13, surefire по умолчанию просто выводит сводку.

     <build>
      <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${your.maven.surefire.version.here}</version>
            <configuration>
                <trimStackTrace>false</trimStackTrace>
            </configuration>
        </plugin>
      </plugins>
    </build>
 

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

1. Это решило проблему. Большое вам спасибо. Ты спас мне жизнь 🙂