抛出 WebServerException:无法使用 Powermock 和 Springboot 启动嵌入式 Tomcat [英] Throw WebServerException: Unable to start embedded Tomcat using Powermock and Springboot

查看:136
本文介绍了抛出 WebServerException:无法使用 Powermock 和 Springboot 启动嵌入式 Tomcat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Springboot 和 junit,我想使用 Powermock 来模拟静态类,添加 Powermock 后,单元测试通过 IntelliJ IDEA 运行良好,但是当我在终端下运行 mvn test 时,它抛出 ApplicationContextException: 无法启动 Web 服务器\n 无法启动嵌入式 Tomcat

I'm using Springboot and junit, I want to use Powermock to mock static class, after added Powermock the unit test runs well through IntelliJ IDEA, but when i run mvn test under terminal, it throws ApplicationContextException: Unable to start web server\n Unable to start embedded Tomcat

我的基础测试类:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WebApplication.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@RunWith(PowerMockRunner.class)
@PowerMockIgnore( {"javax.management.*", "javax.net.*", "javax.crypto.*"})
@Slf4j
@ComponentScan(basePackages = {"com.rolls"})
@ActiveProfiles("test")
@Transactional
@Rollback
public class ApplicationTest {
    ...test
}

测试类:

@Slf4j
@PrepareForTest(ClientCache.class)
public class RuleServiceTest extends ApplicationTest {


    @Mock
    private IClient iClient;

    @Before
    public void setUp() {
        PowerMockito.mockStatic(ClientCache.class);
    }

    ...test
}

相关maven pom.xml:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
    </parent>

        <!--   mock class    -->
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>2.0.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito2</artifactId>
            <version>2.0.2</version>
            <scope>test</scope>
        </dependency>

错误运行mvn test:

[INFO] --- maven-surefire-plugin:3.0.0-M4:test (default-test) @ dq-web ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.rolls.ApplicationTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 36.015 s - in com.rolls.ApplicationTest
[INFO] Running com.rolls.common.utils.DateUtilTest
[ERROR] Tests run: 3, Failures: 0, Errors: 3, Skipped: 0, Time elapsed: 18.619 s <<< FAILURE! - in com.rolls.common.utils.DateUtilTest
[ERROR] com.rolls.common.utils.DateUtilTest.testGetFormattedDate1  Time elapsed: 0.618 s  <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: A child container failed during start
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@5b6afa58]
Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@5b6afa58]
Caused by: java.lang.Error: factory already defined
...
[ERROR] com.rolls.service.impl.RuleServiceTest.testListNotIn  Time elapsed: 0.001 s  <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: A child container failed during start
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
Caused by: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@795c941b]
Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@795c941b]
Caused by: java.lang.Error: factory already defined

似乎@RunWith(PowerMockRunner.class) 无法启动springboot embeded tomcat,但是要使用Powermock,我需要用它运行.

Seems @RunWith(PowerMockRunner.class) couldn't start springboot embeded tomcat, but to use Powermock, i need to run with it.

问题:有人知道如何将 PowermockSpringboot 集成吗?

Question: anyone know how to integrate Powermock with Springboot?

推荐答案

解决方案:我改用 Mockito 3.4.6 而不是 PowerMock

见我的伪代码如下:

我要测试的目标方法

public String paramReplace(String type) {
   ...code here
   IClient client = ClientCache.getClient(type);
   client.execute();
   ...code here
}

public ClientCache {
   public static getClient(String type) {
      ...code here
      return client;
   } 
}

public Client {
   public String execute() {
     ...code here
     return "a";
   }
}

我想测试方法paramReplace(),在这个方法内部,我需要模拟ClientCache.getClient()(一个静态方法)和client.执行().

I want to test method paramReplace(), inner this method, i need to mock ClientCache.getClient()(a static method) and client.execute().

我的测试班:

@Slf4j
public class JobParamReplaceTest extends ApplicationTest {

    @Autowired
    public JobParamReplace jobParamReplace;
    @Mock
    private IClient iClient;
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.openMocks(this);
//        PowerMockito.mockStatic(ClientCache.class);
       
//        iClient = Mockito.mock(IClient.class);
        MockedStatic<ClientCache> clientCache = Mockito.mockStatic(ClientCache.class);
        clientCache.when(() -> ClientCache.getClient(Mockito.anyInt())).thenReturn(iClient);
//        Mockito.when(iClient.executeQuery(Mockito.any(ISourceDTO.class), Mockito.any(SqlQueryDTO.class))).thenReturn(new ArrayList<Map<String, Object>>());
        Mockito.when(iClient.executeQuery(Mockito.any(ISourceDTO.class), Mockito.any(SqlQueryDTO.class))).thenReturn(new ArrayList(1));
    }

    @Test
    public void testParamReplace() throws Exception {
        String sql_res = jobParamReplace.paramReplace("a");
        Assert.assertTrue(StringUtils.isNotBlank(sql_res));
    }
}

基础测试类:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = WebApplication.class)
@RunWith(SpringRunner.class)
@Slf4j
@ComponentScan(basePackages = {"com.dtstack"})
@ActiveProfiles("test")
@Transactional
@Rollback
public class ApplicationTest {

}

我的 maven 依赖:

My maven dependency:

<dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>3.4.6</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <scope>test</scope>
        </dependency>

总结:使用@Mock模拟非静态方法,使用Mockito.mockStatic(ClientCache.class)模拟静态方法

Summary: Use @Mock to mock non-static method, and use Mockito.mockStatic(ClientCache.class) to mock static method

这篇关于抛出 WebServerException:无法使用 Powermock 和 Springboot 启动嵌入式 Tomcat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆