繁体   English   中英

依赖问题:Java SE-1.8、JUnit 5、Mockito 4.0 和 PowerMock

[英]Dependency issue: Java SE-1.8, JUnit 5, Mockito 4.0 and PowerMock

In a project (Eclipse IDE 4.12) with Maven I'm using successfuly JUnit 5 and Mockito 4.0.0 for testing / mockig. 现在,为了测试受保护的方法,我也想使用 PowerMock。

在搜索 web 一段时间后,我最终得到了这个 pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>sdi</groupId>
<artifactId>id4mqtt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Id4Mqtt</name>
<description>Rapid IoT development framework</description>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
</properties>

<repositories>
    <repository>
        <id>Eclipse Paho Repo</id>
        <url>%REPOURL%</url>
    </repository>
</repositories>

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.mockito/mockito-inline -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-inline</artifactId>
        <version>4.0.0</version>
        <scope>test</scope>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.apache.geronimo.gshell.support/gshell-io -->
    <dependency>
        <groupId>org.apache.geronimo.gshell.support</groupId>
        <artifactId>gshell-io</artifactId>
        <version>1.0-alpha-2</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.powermock/powermock-mockito-release-full -->
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-mockito-release-full</artifactId>
        <version>1.6.4</version>
        <type>pom</type>
        <scope>test</scope>
    </dependency>

</dependencies>

要测试的候选人是(删除不感兴趣的代码)

package applicationBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


public class ConfigurationBuilder extends BuilderBase {

    private Properties properties;
    private String[] uriList;
     
    public ConfigurationBuilder(final Properties aProperties) {
        properties = aProperties;
    } // ConfigurationBuilder(...)
    
    public Object build(final String aBrokerName) {

        List<String> brokerList = grepPropertyKey("[^\\.]+\\.CommunicationMode");
        List<MQTTClientDao> clientDaoList = new ArrayList<>();

        for(String broker : brokerList) {
            clientDaoList.add(buildConfig(broker));
        } // rof(broker)
        
        return clientDaoList;
        
    } // build()

    protected MQTTClientDao buildConfig(String broker) {
        
        buildUriList(broker);
        
        return new MQTTClientDao(mqttClient, connectOptions);
        
    } // buildConfig

    protected void buildUriList(final String aBroker) {
        
        ServerUriBuilder builder = new ServerUriBuilder(properties);
        uriList = (String[]) builder.build(aBroker);
        
    } // buildUriList()

} // class

应该测试 ServerUriBuilder.build(properties) 方法的正确调用的测试类如下所示:

package test.applicationBuilder;

import static org.powermock.api.mockito.PowerMockito.*;

import java.util.Properties;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;

import applicationBuilder.ConfigurationBuilder;
import applicationBuilder.ServerUriBuilder;

@RunWith(PowerMockRunner.class)
@PrepareForTest(ServerUriBuilder.class)
class ConfigurationBuilderTest {

    private static Properties properties;
    private static final String BROKER_NAME = "Broker1";
    
    
    @BeforeEach
    void setUp() throws Exception {
        
        properties = new Properties();
        
    }

    @AfterEach
    void tearDown() throws Exception {
        
        properties = null;
        
    }

    @Test
    final void testBuildUriList() {
        
        ConfigurationBuilder cut = spy(new ConfigurationBuilder(properties));
        
        try {
            
            verifyPrivate(cut).invoke("buildUriList", BROKER_NAME);
            
        } catch (Exception e) { e.printStackTrace(); }
        
    } // testBuildUriList()

    
} // class

一切似乎都很好,因为 Eclipse 没有报告错误。 但是当我运行测试时抛出异常:

java.lang.NoClassDefFoundError: org/mockito/cglib/proxy/MethodInterceptor
    at org.powermock.api.mockito.PowerMockito.spy(PowerMockito.java:220)
    at test.applicationBuilder.ConfigurationBuilderTest.testBuildUriList(ConfigurationBuilderTest.java:130)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:628)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:117)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:184)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:180)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:127)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: java.lang.ClassNotFoundException: org.mockito.cglib.proxy.MethodInterceptor
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 55 more


我的问题是:

  1. 我可以使用此组合进行测试吗?
  2. 我的 pom.xml 是否正确并包含所有必需的模块?
  3. 如何使测试运行?

提前致谢!

如果要使用 JUnit5 模拟 static 方法,请添加与 Powermockito 执行相同工作的 Mockito-inline 依赖项。

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

For static methods that do not have arguments, you can use the :: lambda of Java 8. I like to use the try/catch in one line because you don't have to call utilities.close(); 完成测试后。

@Test
void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {
    assertThat(StaticUtils.name()).isEqualTo("string-to-mock");

    try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
        utilities.when(StaticUtils::name).thenReturn("value-name");
        assertThat(StaticUtils.name()).isEqualTo("value-name");
    }
    assertThat(StaticUtils.name()).isEqualTo("string-to-mock");
}

或者对于需要 arguments 的方法

@Test
void givenStaticMethodWithArgs_whenMocked_thenReturnsMockSuccessfully() {
    assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);

    try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
        utilities.when(() -> StaticUtils.range(2, 6))
          .thenReturn(Arrays.asList(10, 11, 12));

        assertThat(StaticUtils.range(2, 6)).containsExactly(10, 11, 12);
    }

    assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
}

运行示例可以在这里找到。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM