I have Junit test case for service layer, from service method logic calling some other beans with autowired and in the unit test case I used that bean as Autowired beacuse that also should cover as part of code coverage.
class CustomerServiceTest{
@Autowired(or InjectMocks)
private EmployeeService employeeService;
@Autowired
private CustomerService customerService;
@Test
public void testcustomerIdNotNull() {
//mocking some repository call
Customer customer = customerService.getCustomerDetails();
//all other test case code
}
}
//Customer Service code
@Service
public class CustomerService{
@Autowired
EmployeeService employeeService;
public Customer getCustomerDetails() {
//some code
employeeService.getEmployee(); /// **Here it was throwing nullpointerexception**
//some logic and complete code
}
}
I tried Autowired with Spy but didn't work.
Your setup is weird. And your comment suggests that you think that @Autowired
and @InjectMocks
are interchangable. They are absolutely not.
The first question you have to ask yourself is if you want to run a Spring Boot test (loading the application context) or if you want to execute a test that uses regular Java without Spring.
If you need a Spring Boot test:
@SpringBootTest
class CustomerServiceTest{
@MockBean // register a mock version of your repository bean
private YourRepository yourRepository;
@Autowired
private CustomerService customerService;
@Test
public void testcustomerIdNotNull() {
// mocking some repository call ...
Customer customer = customerService.getCustomerDetails();
// all other test case code
}
}
If you don't need Spring's application context and want to mock your dependencies:
@ExtendWith(MockitoExtension.class)
class CustomerServiceTest{
@Mock // creates a mock instance
private YourRepository yourRepository;
@InjectMocks // creates a real instance and injects mocks
private CustomerService customerService;
@Test
public void testcustomerIdNotNull() {
// mocking some repository call ...
Customer customer = customerService.getCustomerDetails();
// all other test case code
}
}
@Mock
and @InjectMocks
of Mockito go together as do @MockBean
and @Autowired
of Spring Boot. You must not mix them.
IIRC, @InjectMocks
should be able to inject fields, but if it doesn't move away from the discouraged method of field injection and migrate your class to constructor injection:
@Service
public class CustomerService {
private final EmployeeService employeeService;
@Autowired
public CustomerService(final EmployeeService employeeService) {
this.employeeService = employeeService;
}
public Customer getCustomerDetails() {
//some code
employeeService.getEmployee();
//some logic and complete code
}
}
This has the added benefit of allowing to mark your fields as final.