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;
    }

    ...
}