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

Spring Boot 2单元测试:@Autowired换@MockBean生效的原因咨询

Why @Autowired Fails But @MockBean Works in Your Spring Boot Test

Let's break down exactly what's happening here and why swapping @Autowired for @MockBean fixes your test error.

The Problem with @Autowired in Your Test

When you use @Autowired to inject VehicleRepository, Spring tries to find a real, fully initialized instance of that repository in its application context. But in your test setup:

  • You're only using @RunWith(SpringJUnit4ClassRunner.class)—this starts a basic Spring context, but it doesn't load your full Spring Boot application configuration (like scanning for @Repository beans or setting up database connections).
  • Even if you had a full context, unit testing a service shouldn't depend on a real repository (you don't want to hit a real database or test someone else's code).

Without a real VehicleRepository bean registered in the context, Spring throws that NoSuchBeanDefinitionException—it literally can't find the bean you're asking it to inject.

Why @MockBean Fixes Everything

@MockBean is a Spring Boot Test-specific annotation that solves this problem in two key ways:

  • It creates a mock version of VehicleRepository using the Mockito library (no real database calls, no actual repository logic).
  • It automatically registers this mock bean into the Spring test context. Now when your test runs, Spring sees a bean of type VehicleRepository exists, so it can inject it without errors.

This lets you isolate your service logic: you can define exactly how the mock repository should behave (e.g., return a specific vehicle when findById is called) and test only the code in VehicleServiceImpl.

A Better Test Setup Example

You can simplify your test even more by using @InjectMocks to let Mockito automatically wire the mock repository into your service, instead of manually creating the service instance:

@RunWith(SpringJUnit4ClassRunner.class)
public class VehicleServiceImplTest {
    // Create and register a mock VehicleRepository in the Spring context
    @MockBean
    private VehicleRepository repository;

    // Automatically inject the mock repository into the service
    @InjectMocks
    private VehicleServiceImpl service;

    @Test
    public void testGetVehicleById() {
        // Define mock behavior
        Vehicle testVehicle = new Vehicle();
        testVehicle.setId(1L);
        when(repository.findById(1L)).thenReturn(Optional.of(testVehicle));

        // Test the service method
        Vehicle result = service.getVehicleById(1L);

        // Verify the result
        assertNotNull(result);
        assertEquals(1L, result.getId());
    }
}

If you don't even need the Spring context (for a pure unit test), you can skip Spring's runner entirely and use Mockito's own runner:

@RunWith(MockitoJUnitRunner.class)
public class VehicleServiceImplTest {
    @Mock
    private VehicleRepository repository;

    @InjectMocks
    private VehicleServiceImpl service;

    // Same test method as above
}

Key Takeaways

  • @Autowired is for injecting real Spring-managed beans—use it when you need the actual implementation (e.g., in integration tests).
  • @MockBean is for creating and injecting mock beans into a Spring test context—perfect for unit testing services while isolating external dependencies like repositories.
  • For pure unit tests (no Spring context needed), use @Mock + @InjectMocks with MockitoJUnitRunner.class for a lighter, faster test setup.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:51:31