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

Mockito测试中CartService的@Autowired UserService为null,能否正常测试?

问题原因

你遇到的空指针异常,核心原因是CartService上的@RequiredArgsConstructor注解会生成一个仅包含final修饰字段的构造函数,而@Autowired标注的userService并没有被声明为final,所以不会出现在这个构造函数里。

Mockito的@InjectMocks默认优先使用构造函数注入,因此只会给构造函数里的cartRepository、productRepository、cartItemRepository赋值,完全忽略了userService字段,导致调用时出现null。

解决方案(保留@Autowired注入方式)

方案1:用反射工具手动注入(最通用)

借助Spring的ReflectionTestUtils,在测试初始化阶段把mock的userService手动设置到cartService的私有字段中,不需要修改业务类代码:

@ExtendWith(MockitoExtension.class)
class CartServiceTest {
    @Mock
    private CartRepository cartRepository;
    @Mock
    private CartItemRepository cartItemRepository;
    @Mock
    private UserRepository userRepository;
    @Mock
    private ProductRepository productRepository;
    @Mock
    private UserService userService;
    @InjectMocks
    private CartService cartService;

    @BeforeEach
    void setUp() {
        // 手动注入userService字段
        ReflectionTestUtils.setField(cartService, "userService", userService);
    }

    @Test
    void checkedClearCartFromAllItems(){
        Principal principal = mock(Principal.class);
        User user = mock(User.class);
        when(userService.getUserOfPrincipal(principal)).thenReturn(user);

        cartService.clearCart(principal);
    }
}

方案2:指定Mockito优先使用字段注入

如果不想用反射,可以调整Mockito的注入策略,让它优先通过字段注入而不是构造函数注入。需要手动初始化cartService并指定注入器:

@ExtendWith(MockitoExtension.class)
class CartServiceTest {
    @Mock
    private CartRepository cartRepository;
    @Mock
    private CartItemRepository cartItemRepository;
    @Mock
    private UserRepository userRepository;
    @Mock
    private ProductRepository productRepository;
    @Mock
    private UserService userService;
    private CartService cartService;

    @BeforeEach
    void setUp() {
        // 先通过构造函数初始化cartService
        cartService = new CartService(cartRepository, productRepository, cartItemRepository);
        // 开启Mock并指定用字段注入策略
        MockitoAnnotations.openMocks(this, MockitoInjector.STRICT_STUBS);
    }

    @Test
    void checkedClearCartFromAllItems(){
        Principal principal = mock(Principal.class);
        User user = mock(User.class);
        when(userService.getUserOfPrincipal(principal)).thenReturn(user);

        cartService.clearCart(principal);
    }
}

注:虽然Spring官方更推荐@RequiredArgsConstructor+构造函数注入的方式(更利于测试和依赖透明性),但以上两种方案都能满足你保留@Autowired注入userService的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:06:31