I have a controller with constructor injection
@RestController
@RequestMapping("/user")
public class MainController {
private final UserMapper userMapper; // autowired by constructor below
public MainController(UserMapper userMapper) {
this.userMapper = userMapper;
}
@RequestMapping("/getChannels")
public String index() {
LoginUser user = userMapper.getUserByName("admin");
return "Channels: " + user.getChannels();
}
}
It's a simple class which is working fine. However when I tried to run a JUnit testing with below class I got an error.
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class MainControllerTest {
private MockMvc mvc;
private final UserMapper userMapper;
public MainControllerTest(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new MainController(userMapper)).build();
}
......
The error is:
java.lang.Exception: Test class should have exactly one public zero-argument constructor
I was confused by above error message that how could I inject the userMapper with a zero-argument constructor? I know it's possible to add the @Autowired for userMapper in MainController however the field injection is not recommended. Please could anybody guide me a suitable way for both constructor injection and MockMvc testing. Thanks.
MockMVC class is part of Spring MVC test framework which helps in testing the controllers explicitly starting a Servlet container. In this MockMVC tutorial, we will use it along with Spring boot's WebMvcTest class to execute Junit testcases which tests REST controller methods written for Spring boot 2 hateoas example.
Unit Tests should be written under the src/test/java directory and classpath resources for writing a test should be placed under the src/test/resources directory. For Writing a Unit Test, we need to add the Spring Boot Starter Test dependency in your build configuration file as shown below.
MockMvc provides support for Spring MVC testing. It encapsulates all web application beans and makes them available for testing. We'll initialize the mockMvc object in the @BeforeEach annotated method, so that we don't have to initialize it inside every test.
Other answers talk about using annotations, but here your problem doesn't have any relation to using annotations. keep in mind as spring 4.3+ you don't need to annotate constructor for dependencies, see more here.
In fact You don't need to try to simulate constructor injection in your Test class (MainControllerTest
).
All you need is to declaring UserMapper
as spring component in your application context and in your test class it will be auto injected in your controller as your running application.
Whats your error mean: All of Junit Test classes as error message says should have exactly one public zero-argument constructor that's because Junit Test suites in cases like your scenario doesn't know how to instantiate Test class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With