我有一个带构造函数注入的控制器
@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();
}
}
这是一个工作正常的简单课程。但是,当我尝试使用以下类运行JUnit测试时,我收到了错误。
@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();
}
......
错误是:
java.lang.Exception: Test class should have exactly one public zero-argument constructor
我对上面的错误消息感到困惑,我怎么能用一个零参数构造函数注入userMapper? 我知道可以在MainController中为userMapper添加@Autowired,但不建议使用字段注入。 请任何人指导我一个适合构造函数注入和MockMvc测试的方法。感谢。
答案 0 :(得分:1)
在该字段上使用@Autowire。在生产代码中不建议使用现场注入,因为它会使推理变得混乱(注入的位置和原因)。但测试环境(尤其是那些像这样的环境)很简单,因此存在难以推理的缺陷。
@Autowired
private final UserMapper userMapper;
public MainControllerTest() { //remove me, implicit
}
此更改将解决问题,因为jUnit将具有它理解的构造函数,并且能够实例化测试类。
答案 1 :(得分:1)
其他答案谈论使用注释,但这里你的问题与使用注释没有任何关系。请记住,在4.3以上版本中,您不需要为构造函数注释依赖项see more here。
实际上,您不需要尝试在Test类(MainControllerTest
)中模拟构造函数注入。
您所需要的只是在应用程序上下文中将UserMapper
声明为spring组件,在测试类中,它将作为正在运行的应用程序自动注入控制器中。
你的错误是什么意思:所有Junit Test类都是错误消息,说应该只有一个公共零参数构造函数,因为Junit Test套件就像你的场景一样没有&#39 ; t知道如何实例化Test类。
答案 2 :(得分:-1)
您缺少@Autowired
构造函数的MainController
,并始终使用构造函数注入,如下所示解决此问题:
@RestController
@RequestMapping("/user")
public class MainController {
private final UserMapper userMapper;
@Autowired
public MainController(UserMapper userMapper) {
this.userMapper = userMapper;
}
//add methods here
}
使用字段注入不是最佳做法,请查看here以获取更多详细信息。
另外,要解决此问题,您需要更新Test类,如下所示:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class MainControllerTest {
private MockMvc mvc;
@Mock
private UserMapper userMapper;
@InjectMocks
private MainController mainController = new MainController(userMapper);
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(mainController)..build();
}
......
}