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

Mockito测试报错:无法实例化@InjectMocks标注的UserServiceImpl

Mockito @InjectMocks 无法实例化继承抽象类的服务类问题解决

报错信息

Cannot instantiate @InjectMocks field named 'userService' of type 'UserServiceImpl'. You haven't provided the instance at field declaration so I tried to construct the instance.

场景说明

UserServiceImpl继承AbstractPagingService<User, Integer, UserEntity>后触发上述报错,不继承该抽象类时测试正常。相关代码如下:

UserService接口

public interface UserService {
    Optional<User> getByToken(String token);
    PagingDto<User> getUsers(String filter, Integer startIndex, Integer count);
}

UserServiceImpl实现类

public class UserServiceImpl extends AbstractPagingService<User, Integer, UserEntity> implements UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserServiceImpl(ProviderConfiguration providerConfiguration, UserRepository userRepository) {
        super(providerConfiguration.getFilter().getMaxResult(), userRepository, Sort.by("surname"));
        this.userRepository = userRepository;
    }
    // 业务方法省略
}

测试类

@ExtendWith(SpringExtension.class)
class UserServiceImplTest {
    private static final String TOKEN = "token";

    @InjectMocks
    private UserServiceImpl userService;

    @Spy
    private UserRepository userRepository;

    // 测试方法省略
}

问题原因

Mockito的@InjectMocks自动实例化对象时,会优先调用类的构造方法。当前UserServiceImpl的构造方法需要两个参数:ProviderConfiguration和UserRepository,但测试类里只提供了UserRepository的Spy实例,缺了ProviderConfiguration的实例,导致Mockito无法完成构造。而继承抽象类后,Mockito的实例化逻辑会更严格,没有 fallback 路径,所以直接抛出报错。

解决方案

方案1:补充ProviderConfiguration的Mock实例

在测试类中添加ProviderConfiguration的Mock,并模拟其必要的返回值,让Mockito能调用构造方法完成实例化。

@ExtendWith(SpringExtension.class)
class UserServiceImplTest {
    private static final String TOKEN = "token";

    @InjectMocks
    private UserServiceImpl userService;

    @Spy
    private UserRepository userRepository;
    
    // 添加ProviderConfiguration的Mock
    @Mock
    private ProviderConfiguration providerConfiguration;

    @BeforeEach
    void setUp() {
        // 模拟providerConfiguration的getFilter().getMaxResult()返回值
        FilterConfig filterConfig = mock(FilterConfig.class);
        when(filterConfig.getMaxResult()).thenReturn(10); // 根据业务需求设置数值
        when(providerConfiguration.getFilter()).thenReturn(filterConfig);
    }

    // 原测试方法保留
}

方案2:手动实例化UserServiceImpl

直接在初始化方法里手动创建服务类实例,传入所需的Mock对象,完全控制实例化过程,绕开@InjectMocks的自动构造逻辑。

@ExtendWith(SpringExtension.class)
class UserServiceImplTest {
    private static final String TOKEN = "token";

    private UserServiceImpl userService;

    @Spy
    private UserRepository userRepository;
    
    @Mock
    private ProviderConfiguration providerConfiguration;

    @BeforeEach
    void setUp() {
        // 模拟必要的依赖返回值
        FilterConfig filterConfig = mock(FilterConfig.class);
        when(filterConfig.getMaxResult()).thenReturn(10);
        when(providerConfiguration.getFilter()).thenReturn(filterConfig);
        
        // 手动实例化服务类
        userService = new UserServiceImpl(providerConfiguration, userRepository);
    }

    // 原测试方法保留
}

总结

本质是构造方法的依赖参数未在测试中齐全,继承抽象类后Mockito的实例化逻辑不再有 fallback,必须满足构造方法的参数要求。补充缺失的Mock或者手动实例化服务类,就能解决这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 16:55:31