You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何验证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)
...(省略部分栈追踪内容)

问题原因

  1. mock对象未关联:创建的Account mock对象并没有被Student实例使用,Student内部还是新建了真实的Account对象,验证mock对象的方法调用自然失败。
  2. 错误mock了Student构造:目标是验证Account.init(),不需要mockStudent本身,反而应该让真实的Student构造执行,仅替换它内部的Account实例。
  3. 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注解。
  • 无需mockStudent类本身,直接创建真实实例即可,这样构造函数会正常执行,调用mock的Account.init()方法。

内容的提问来源于stack exchange,提问作者taetaetae

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:06:21