Java Mockito:调用真正的实现
我正在尝试为我的控制器类编写单元测试。但它不是在模仿Java Mockito:调用真正的实现,java,spring,unit-testing,mockito,Java,Spring,Unit Testing,Mockito,我正在尝试为我的控制器类编写单元测试。但它不是在模仿EmployeeBusinessLogic,而是在调用真正的方法调用 public class Controller { @RequestMapping(value="/GetAllEmployeeDetails", method=RequestMethod.GET, produces="application/json") public List<Employee> GetAllEmployeeDetails()
EmployeeBusinessLogic
,而是在调用真正的方法调用
public class Controller {
@RequestMapping(value="/GetAllEmployeeDetails", method=RequestMethod.GET, produces="application/json")
public List<Employee> GetAllEmployeeDetails() {
EmployeeBussinessLogic empbl = new EmployeeBussinessLogic();
return empbl.GetAllEmployeeDetails();
}
下面是我的控制器测试代码
public class ControllerTestWithMockito {
@Mock
EmployeeBussinessLogic empBusLgcObj;
@Mock
EmployeeDAO mockEmployeeDAO;
@InjectMocks
@Autowired
Controller ctrlObj;
@Before
public void create()
{
MockitoAnnotations.initMocks(this);
List<Employee> empList = new ArrayList<Employee>();
empList.add(new Employee(1, "Emp1", 23, 1000));
empList.add(new Employee(2, "Emp2", 24, 2000));
Mockito.when(empBusLgcObj.GetAllEmployeeDetails()).thenReturn(empList);
}
@Test
public void getAllEmployeeDetailstest() {
final List<Employee> expectedEmpList = new ArrayList<Employee>();
expectedEmpList.add(new Employee(1, "Emp1", 23, 1000));
expectedEmpList.add(new Employee(2, "Emp2", 24, 2000));
final List<Employee> actualEmpList = ctrlObj.GetAllEmployeeDetails();
Assert.assertTrue(actualEmpList.size() == expectedEmpList.size());
Assert.assertTrue(actualEmpList.equals(expectedEmpList));
}
}
public class ControllerTestWithMockito{
@嘲弄
员工业务逻辑empBusLgcObj;
@嘲弄
EmployeeDAO模拟EmployeeDAO;
@注射模拟
@自动连线
控制器ctrlObj;
@以前
公共void create()
{
initMocks(this);
List empList=new ArrayList();
添加(新员工(1,“Emp1”,231000);
添加(新员工(2,“Emp2”,2000年12月24日);
Mockito.when(empBusLgcObj.GetAllEmployeeDetails())。然后返回(empList);
}
@试验
public void getAllEmployeeDetailstest(){
最终列表expectedEmpList=new ArrayList();
expectedEmpList.add(新员工(1,“Emp1”,231000));
expectedEmpList.add(新员工(2,“Emp2”,2000年12月24日);
最终列表ActualPlist=ctrlObj.GetAllEmployeeDetails();
Assert.assertTrue(actualPlist.size()==expectedEmpList.size());
Assert.assertTrue(ActualPlist.equals(expectedEmpList));
}
}
尝试更改为:
Mockito.doReturn(empList).when(empBusLgcObj).GetAllEmployeeDetails();
为了防止在spies中调用real方法,请不要在控制器中使用
new
创建新实例。这段代码不稳定。使用注射代替:
public class Controller {
@Inject
private EmployeeBusinessLogic empbl;
@RequestMapping(value="/GetAllEmployeeDetails", method=RequestMethod.GET, produces="application/json")
public List<Employee> GetAllEmployeeDetails() {
return empbl.GetAllEmployeeDetails();
}
公共类控制器{
@注入
私人雇员商业逻辑empbl;
@RequestMapping(value=“/GetAllEmployeeDetails”,method=RequestMethod.GET,products=“application/json”)
公共列表GetAllEmployeeDetails(){
返回empbl.GetAllEmployeeDetails();
}
Andreas\D正确地认为应该使用注入,而不是在方法GetAllEmployeeDetails
中实例化要模拟的对象
我只想补充一点,您应该更喜欢构造函数注入。它使您的代码更加灵活
public class Controller{
private final EmployeeBussinessLogic employeeBusinessLogic;
@Autowired
public Controller(final EmployeeBussinessLogic employeeBusinessLogic){
this.employeeBusinessLogic = employeeBusinessLogic;
}
...
}
您还可以选择将注入委派给另一个类。当类EmployeeBusinessLogic
和EmployeeDAO
位于web层使用的另一个库中时,这会很有用
@Configuration
public class SpringConfig{
@Bean
public EmployeeBusinessLogic employeeBusinessLogic{
return new EmployeeBusinessLogicImpl(new EmployeeDAOImpl());
}
}
然后,EmployeeBusinessLogic可以在库中无需注释的情况下实现
public class EmployeeBussinessLogic {
private final EmployeeDAO employeeDAO;
public EmployeeBussinessLogic(final EmployeeDAO employeeDAO)
{
this.employeeDAO = employeeDAO;
}
...
}
您可以使用MockitoJUnitRunner使代码更基于注释-检查@RunWith(MockitoJUnitRunner.class)需要更改的行是Mockito.when(empBusLgcObj.GetAllEmployeeDetails()).thenReturn(empList);另外,括号错误,替换代码是doReturn(empList)。when(empBusLgcObj.GetAllEmployeeDetails());那是正确的,谢谢你发现了这一点。。在()时,我把我的答案放在fast上并遵循标准过程语义仍将进入实际的函数调用。请查看@Andreas_D答案。结合我的答案,解决方案将起作用。问题不是关于控制器,而是关于模仿EmployeeBusiness逻辑问题是他想监视EBL,但由于EBL不是注入的,而是在方法内部创建的,因此Controller永远不会使用spy。@InjectMocks要求Mockito可以进行一些注入,无论是字段、方法还是构造函数注入。关于这个问题,他想知道为什么他的mock(spy)会这样做从未调用。我的答案和解决方案。好的,我现在理解你的答案,但这不是他的问题的完整解决方案,他的代码中有两个错误。你的答案解决了其中一个错误。Mockito通过注入设置字段,如中所述,并且用new实例化的对象确实不会被Mockito模拟。
public class EmployeeBussinessLogic {
private final EmployeeDAO employeeDAO;
public EmployeeBussinessLogic(final EmployeeDAO employeeDAO)
{
this.employeeDAO = employeeDAO;
}
...
}