如何验证Student构造函数中私有字段的account.init()方法执行情况?
问题:验证私有成员变量的方法调用失败
原代码实现
Account类
public class Account { public void init(){ System.out.println("init account"); } }
Student类
public class Student { private final Account account = new Account(); public Student() { account.init(); } }
测试依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency>
原测试代码(执行失败)
import static org.mockito.Mockito.*; import static org.powermock.api.mockito.PowerMockito.*; import org.junit.jupiter.api.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; @RunWith(PowerMockRunner.class) @PrepareForTest(Student.class) class TTestTest { @Test public void test() throws Exception { Student tTestMock = PowerMockito.mock(Student.class); whenNew(Student.class).withNoArguments().thenReturn(tTestMock); Account personMock = PowerMockito.mock(Account.class); Student tTest = new Student(); verifyNew(Student.class); verify(personMock, times(1)).init(); // fail } }
报错信息
init account
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-> at com.example.privatefieldmockingtest.StudentTest.test(StudentTest.java:22)Example of correct verification:
verify(mock).doSomething()Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods cannot be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.at com.example.privatefieldmockingtest.StudentTest.test(StudentTest.java:23) ...(省略部分栈追踪内容)
问题原因
- mock对象未关联:创建的
Accountmock对象并没有被Student实例使用,Student内部还是新建了真实的Account对象,验证mock对象的方法调用自然失败。 - 错误mock了Student构造:目标是验证
Account.init(),不需要mockStudent本身,反而应该让真实的Student构造执行,仅替换它内部的Account实例。 - JUnit注解混用:同时使用JUnit 4的
@RunWith和JUnit 5的@Test,导致PowerMock无法正常拦截对象创建流程。
修正后的测试代码
import static org.mockito.Mockito.verify; import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.whenNew; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(Student.class) public class StudentTest { @Test public void testAccountInitIsCalled() throws Exception { // 1. 创建Account的mock对象 Account accountMock = mock(Account.class); // 2. 拦截Student内部创建Account的操作,替换为mock对象 whenNew(Account.class).withNoArguments().thenReturn(accountMock); // 3. 创建真实Student实例,内部account会使用mock对象 new Student(); // 4. 验证mock对象的init方法被调用一次 verify(accountMock).init(); } }
关键说明
- 用
whenNew(Account.class).withNoArguments().thenReturn(accountMock)拦截Student内部的new Account()操作,确保Student使用的是我们的mock对象。 - 必须使用JUnit 4的
@Test注解,和@RunWith(PowerMockRunner.class)配合,禁止混用JUnit 5注解。 - 无需mock
Student类本身,直接创建真实实例即可,这样构造函数会正常执行,调用mock的Account.init()方法。
内容的提问来源于stack exchange,提问作者taetaetae
相关产品推荐
相关产品推荐

