JMockit测试静态方法遇空指针异常,求正确测试及PowerMock实现
Alright, let's dive into what's causing that NullPointerException and fix it, plus walk through how to implement this test with PowerMock if you switch over.
一、Your Core Mistake
The root of your NPE is how you're initializing entityClass:
entityClass = User.class.getClass();
When you call getClass() on User.class, you're getting the Class object for the Class type itself (so Class<Class>), not the Class<User> object you need. When this gets passed to findTableName, the method tries to look for the @Table annotation on the Class class (which doesn't exist), so table ends up null, and calling table.name() throws the NPE.
二、Correct JMockit Implementation
First, fix the initialization, then adjust your test setup (and watch out for runner conflicts):
Fixed Test Code
import org.jmockit.Deencapsulation; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.assertEquals; // Note: If using JMockit, use its runner instead of Mockito's to avoid conflicts // @RunWith(JMockit.class) public class QueryGeneratorTest { private static Class<User> entityClass; @BeforeClass public static void initial() { // Just assign User.class directly—no extra getClass() call needed entityClass = User.class; } @Test public void testGenerateQuery_findTableName(){ String result = Deencapsulation.invoke(QueryGenerator.class, "findTableName", entityClass); assertEquals("user", result); } }
Quick Notes
- If you're using
@SpringBootTestalongside JMockit, make sure your dependencies are properly ordered, and avoid mixingMockitoJUnitRunnerwith JMockit's runner—this can cause classloading issues. - Double-check that your
Userclass actually has the@Table(name = "user")annotation applied; without it, you'll still get an NPE whentableis null.
三、Switching to PowerMock
If you want to use PowerMock instead, here's how to set it up:
1. Add PowerMock Dependencies
Update your pom.xml with these dependencies (compatible with JUnit 4):
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency>
2. PowerMock Test Code
import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.junit.Assert.assertEquals; @RunWith(PowerMockRunner.class) // You must prepare the target class for testing so PowerMock can modify its bytecode @PrepareForTest(QueryGenerator.class) public class QueryGeneratorPowerMockTest { @Test public void testFindTableName() throws Exception { // Invoke the private static method directly String result = PowerMockito.invokeStaticMethod(QueryGenerator.class, "findTableName", User.class); assertEquals("user", result); } }
PowerMock Tips
- The
@PrepareForTestannotation is mandatory here—it tells PowerMock to instrument theQueryGeneratorclass so you can access its private methods. - Again, ensure your
Userclass has the correct@Tableannotation to avoid the same NPE issue.
内容的提问来源于stack exchange,提问作者Farzane Sadeghi

