parag mangal
parag mangal

Reputation: 59

Mockito : Calling real implementation

I am trying to write unit test for my controller class. But instead of mocking EmployeeBussinessLogic it is invoking real method call.

public class Controller {

    @RequestMapping(value="/GetAllEmployeeDetails", method=RequestMethod.GET, produces="application/json")
    public List<Employee> GetAllEmployeeDetails() {

        EmployeeBussinessLogic empbl = new EmployeeBussinessLogic();
        return empbl.GetAllEmployeeDetails();

   }

following is the EmployeeBussinessLogic class

public class EmployeeBussinessLogic {

    @Autowired
    EmployeeDAO employeeDAO;

    public EmployeeBussinessLogic()
    {
         employeeDAO = new EmployeeDAOImpl();
    }

    public EmployeeBussinessLogic(EmployeeDAO explicityEmployeeDAO)
    {
        employeeDAO = explicityEmployeeDAO;
    }

    public List<Employee>  GetAllEmployeeDetails()
    {
        List<Employee> EmployeeList = employeeDAO.listOfEmployees();

        String text = "";

        for(Employee emp : EmployeeList)
        {
            text =  "Emp ID = " + emp.getEmployeeId() +
                " Emp Age = " + emp.getEmployeeAge() + 
                " Emp Name = " + emp.getEmployeeName() + 
                " Emp Salary = " + emp.getEmployeeSalary().toString().trim() + "\n";

            System.out.println(text);
        }
        return EmployeeList ;
    }
}

Following is my controller test code

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

}

Upvotes: 2

Views: 1157

Answers (3)

Maciej Kowalski
Maciej Kowalski

Reputation: 26512

Try changing to this:

Mockito.doReturn(empList).when(empBusLgcObj).GetAllEmployeeDetails();

That prevents calling the real method in spies

Upvotes: 1

nille85
nille85

Reputation: 311

Andreas_D is right that you should use injection instead of instantiating the object that you want to mock in the method GetAllEmployeeDetails.

I only want to add that you should prefer constructor injection. It makes your code more flexible.

public class Controller{

    private final EmployeeBussinessLogic  employeeBusinessLogic;

    @Autowired
    public Controller(final EmployeeBussinessLogic  employeeBusinessLogic){
        this.employeeBusinessLogic = employeeBusinessLogic;
    }

    ...

}

You can also choose to delegate the injection to another class. This can be usefull when the classes EmployeeBusinessLogic and EmployeeDAO are located in another library which your web layer uses.

@Configuration
public class SpringConfig{


    @Bean
    public EmployeeBusinessLogic employeeBusinessLogic{
        return new EmployeeBusinessLogicImpl(new EmployeeDAOImpl());
    }

} 

EmployeeBusinessLogic can then be implemented without annotations in your library.

public class EmployeeBussinessLogic {

    private final EmployeeDAO employeeDAO;

    public EmployeeBussinessLogic(final EmployeeDAO employeeDAO)
    {
         this.employeeDAO = employeeDAO;
    }

    ...
}

Upvotes: 0

Andreas Dolk
Andreas Dolk

Reputation: 114767

In your controller, do not create a new instance with new. This code is untestable. Use injection instead:

public class Controller {

    @Inject
    private EmployeeBusinessLogic empbl;

    @RequestMapping(value="/GetAllEmployeeDetails", method=RequestMethod.GET, produces="application/json")
    public List<Employee> GetAllEmployeeDetails() {

        return empbl.GetAllEmployeeDetails();
    }

Upvotes: 1

Related Questions