Ivan Vilanculo
Ivan Vilanculo

Reputation: 668

WebMvcTest attempts to load every application Controller

When I try to implement a WebMvcTest it attempts to instantiate every application controller rather than just the one indicated on the @WebMvcTest annotation.

Without any luck or success, I've read these articles:

And here are the parts of my code that I found relevant

@SpringBootApplication
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}
@RestController
@RequestMapping("/api/complaints/{id}/comments")
public class CommentController {

  @PostMapping
  public CommentJson comment(@PathVariable String id, @RequestBody CommentCommand command) {
    throw new UnsupportedOperationException("Method not implemented yet");
  }
}
@WebMvcTest(CommentController.class)
class CommentControllerTest extends AbstractTest {

  @Autowired
  MockMvc mockMvc;
  // ...
}

When I run the tests it fails with the following error:

Parameter 0 of constructor in com.company.package.controller.ComplaintController required a bean of type 'com.company.package.service.Complaints' that could not be found.
@RestController
@RequestMapping("/api/complaints")
@RequiredArgsConstructor
@ControllerAdvice()
public class ComplaintController {
  private final Complaints complaints;

  // ... other controller methods

  @ExceptionHandler(ComplaintNotFoundException.class)
  public ResponseEntity<Void> handleComplaintNotFoundException() {
    return ResponseEntity.notFound().build();
  }
}
@ExtendWith(MockitoExtension.class)
public abstract class AbstractTest {
  private final Faker faker = new Faker();

  protected final Faker faker() {
    return faker;
  }

  // ... other utility methods
}

The only way I found to make my Web Mvc Tests run is to mock every dependency of each controller on all @WebMvcTest which is very tedious.
Am I missing something here?

Upvotes: 1

Views: 1819

Answers (1)

rieckpil
rieckpil

Reputation: 12051

While taking a close look at your ComplaintController, you annotate it with @ControllerAdvice

The Javadoc of @WebMvcTest says the following about the relevant MVC beans that are part of the Spring Context for your test:

/**
 * Annotation that can be used for a Spring MVC test that focuses <strong>only</strong> on
 * Spring MVC components.
 * <p>
 * Using this annotation will disable full auto-configuration and instead apply only
 * configuration relevant to MVC tests (i.e. {@code @Controller},
 * {@code @ControllerAdvice}, {@code @JsonComponent},
 * {@code Converter}/{@code GenericConverter}, {@code Filter}, {@code WebMvcConfigurer}
 * and {@code HandlerMethodArgumentResolver} beans but not {@code @Component},
 * {@code @Service} or {@code @Repository} beans).
 * ...
 */

So any @ControllerAdvice is part of this MVC context and hence that's the expected behaviour.

To fix this you could extract your exception handling out of your ComplaintController into a dedicated class that does depend on any other Spring Beans and can be instantiated without mocking anything.

PS: The word all is misleading inside the title of your question WebMvcTest attempts to load every application Controller.

Upvotes: 2

Related Questions