如何测试带有依赖的Spring Boot控制器?(JUnit)
Got it, let's fix this issue step by step!
Why This Happens
The @WebMvcTest annotation is a slice test designed specifically for testing Spring MVC controllers. It only initializes components related to MVC (like controllers, request handlers, and view resolvers) — it doesn't load your full Spring application context. That's why Spring can't find your AnnoyingServiceWhichIsADependency bean: it's not being registered in the test context.
Solutions
1. Mock the Dependency (Recommended for Unit Tests)
Since controller tests should focus on the controller's logic (not the service's implementation), use @MockBean to create a mock instance of your service. Spring will automatically inject this mock into your controller:
@RunWith(SpringRunner.class) @WebMvcTest(ClassToBeTested.class) public class ClassToBeTestedTests { @Autowired private MockMvc mockMvc; // Create a mock of your dependency @MockBean private AnnoyingServiceWhichIsADependency annoyingDependency; @Test public void simpleTestMethodToGetClassWorking(){ Assert.assertTrue(true); } // Example: Test controller logic with mocked service behavior @Test public void testControllerEndpoint() throws Exception { // Define what the mock service should return when(annoyingDependency.someMethod()).thenReturn("test response"); // Perform a request and validate the result mockMvc.perform(get("/your-controller-endpoint")) .andExpect(status().isOk()) .andExpect(content().string("test response")); } }
2. Import the Real Service (Use Sparingly)
If you absolutely need the real service implementation in your test, use @Import to add it to the test context:
@RunWith(SpringRunner.class) @WebMvcTest(ClassToBeTested.class) @Import(AnnoyingServiceWhichIsADependency.class) public class ClassToBeTestedTests { @Autowired private MockMvc mockMvc; @Test public void simpleTestMethodToGetClassWorking(){ Assert.assertTrue(true); } }
⚠️ Note: If your service has its own dependencies, you'll need to import those too — this can quickly make your test complex and defeat the purpose of a slice test.
3. Use Full Context Integration Test
If you need to test the complete end-to-end flow (controller + service + dependencies), switch to @SpringBootTest with @AutoConfigureMockMvc:
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class ClassToBeTestedTests { @Autowired private MockMvc mockMvc; @Test public void simpleTestMethodToGetClassWorking(){ Assert.assertTrue(true); } }
This loads your full application context, so all beans are initialized. Keep in mind this is slower than a slice test, so reserve it for integration scenarios.
Final Recommendation
Stick with Option 1 for most controller unit tests. Mocking dependencies keeps your tests fast, focused, and isolated from changes in other parts of your application.
内容的提问来源于stack exchange,提问作者Slippy

