【发布时间】:2022-01-02 19:45:33
【问题描述】:
在一个带有 Maven 的项目(Eclipse IDE 4.12)中,我成功地使用了 JUnit 5 和 Mockito 4.0.0 进行测试/模拟。现在,为了测试受保护的方法,我也想使用 PowerMock。
在网上搜索了一段时间后,我最终得到了这个 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
我的问题是:
- 我可以使用此组合进行测试吗?
- 我的 pom.xml 是否正确并包含所有必需的模块?
- 如何进行测试?
提前致谢!
【问题讨论】:
-
Powermockito 是基于 JUnit 4 的
@RunWith(PowerMockRunner.class)这表明......这不适用于 JUnit Jupiter(又名 Junit 5。)......另一个问题是:为什么需要 powermockito?为什么不使用 mockito 呢?buildUril....方法是受保护但不是私有的?... -
在使用junit5时最好和mockito-inline一起使用来代替powermock
-
@khmarbaise:这里stackoverflow.com/a/34093433/5564903 解释了如何测试受保护的方法。但是这三种解决方案都不是我可以接受的。既不喜欢将生产代码和测试代码混合在同一个包中,也不喜欢仅仅为了可测试性而更改生产代码。测试代码中的包装器类也不是一个选项,因为被测试的类有很多私有方法要测试......接下来是我有更多的构建器类要测试,它们都遵循相同的基本模式。使用包装器类,每个测试都有相同的丑陋且容易出错的包装器。
-
@Felipe:使用 mockito-inline 时测试会是什么样子?可以举个例子吗?
标签: java maven junit mockito powermock