I want to write a unit test for the following class;
I have started to implement the test and decided to mock "methodNotReadOnly" method first
but end up with null
routeQueryAdvisor object
and it does not matter. for using #Autowired or #InjectMock annotation?
How could I improve this?
Thanks.
RouteQueryAdvisor.class
#Aspect
#Component
#Order(0)
public class RouteQueryAdvisor {
private static final Log log = LogFactory.getLog(RouteQueryAdvisor.class);
private final DbHolder dbHolder;
public RouteQueryAdvisor(DbHolder dbHolder) {
this.dbHolder = dbHolder;
}
#Pointcut(value = "execution(* org.service.domain.rest.service.public_api.impl.*.*(..))")
public void aroundQueryPointCut() {
// Limit the observed transactions for db routing
}
#Around("aroundQueryPointCut()")
public Object proceed(ProceedingJoinPoint pjp) throws Throwable {
try {
if (methodNotReadOnly(pjp)) {
log.info("Proceeding on primary db - write for method " + pjp.getSignature().getName());
return pjp.proceed();
}
log.info("Proceeding on read db " + pjp.getSignature().getName());
Object res = pjp.proceed();
dbHolder.clearDbType();
return res;
} finally {
// clears the db context for next transaction
dbHolder.clearDbType();
}
}
private boolean methodNotReadOnly(#NotNull ProceedingJoinPoint pjp) {
return Arrays.stream(pjp.getTarget().getClass().getDeclaredMethods())
.filter(m -> m.isAnnotationPresent(RouteReadOnlyDB.class))
.filter(n -> n.getName().equals(pjp.getSignature().getName())).findAny().isEmpty();
}
}
Test class:
#PrepareOnlyThisForTest({Method.class})
public class RouteAspectTestMockedMethod {
#Autowired
private RouteQueryAdvisor routeQueryAdvisor;
#Mock
private ProceedingJoinPoint joinPoint;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testIdParamNotFound() throws Throwable {
Mockito.doReturn(routeQueryAdvisor.methodNotReadOnly(joinPoint)).doReturn(true);
Object o = routeQueryAdvisor.proceed(joinPoint);
}
}
Related
I am trying to write Junit test cases for a void method. This method is used for updating values in Database. I have tried certain test cases and its returning a success. But when I check the coverage its showing zero. Can anyone tell me the proper way to write test cases for void methods.
this is my service class :
public class CustomerServiceImpl implements CustomerService {
#Autowired
ERepository eRepository;
#Autowired
ActivityUtil activityUtil;
#Override
public void updateCustomer(RequestDTO requestDTO)
throws CustomAException {
if (Objects.nonNull(requestDTO.getAdmissionId())) {
Optional<Admission> optionalAdmission = eRepository.findById(
requestDTO.getAdmissionId());
if (optionalAdmission .isPresent()) {
EAdmission eAdmission = optionalAdmission.get();
updateCustomer(requestDTO, eAdmission);
} else {
throw new CustomAException ("Admission details not found");
}
}
else {
throw new CustomAException ("Admission id not found");
}
}
private void updateCustomer(RequestDTO requestDTO,
EAdmission eAdmission)
throws CustomAException {
logger.info("updating customer info");
try {
if (ObjectUtils.isNotEmpty(eAdmission.getCustomer())) {
eAdmission.getCustomer().setCustomerEmailAddress(
requestDTO.getEmail());
eAdmission.getCustomer().setCorporateTelephoneNumber(
requestDTO.getCustomerPhone());
eAdmission.getCustomer().setZipCode(requestDTO.getZipCode());
eAdmission.getCustomer().setCustomerAddress1(requestDTO.getAddress1());
evfAdmissionRepository.save(evfAdmission);
activityUtil.createActivityLog(eAdmission, Constants.ENTRY_COMPLETED);
} else {
throw new CustomAException ("Customer details not found ");
}
} catch (Exception exception) {
logger.error(Constants.CUSTOMER_UPDATE_ERROR_MESSAGE);
throw new CustomAException (Constants.CUSTOMER_UPDATE_ERROR_MESSAGE);
}
I am trying to write test cases for updateCustomer but my test class has zero coverage even though its a success.
test class :
#SpringBootTest
public class CustomerServiceImplTest {
#InjectMocks
CustomerServiceImpl CustomerServiceImpl;
#Mock
ERepository eRepository ;
#Mock
ActivityUtil activityUtil;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCustomerException() throws Exception {
CustomerServiceImpl CustomerServiceImplTest = mock(CustomerServiceImpl.class);
when(evfAdmissionRepository.findById(any())).thenThrow(ConstraintViolationException.class);
Mockito.doThrow(CustomAException .class).when(CustomerServiceImplTest).updateCustomer(setRequestDTO());
}
#Test
public void updateCustomerSuccess() throws Exception {
CustomerServiceImpl CustomerServiceImplTest = mock(CustomerServiceImpl.class);
CustomerServiceImplTest .updateCustomer(setRequestDTO());
//doNothing().when(evfCustomerServiceImpl).updateEVFCustomerOnSubscribe(any());
verify(CustomerServiceImplTest ).updateCustomerOn(setRequestDTO());
}
private RequestDTO setRequestDTO() {
RequestDTO eRequestDTO = new RequestDTO ();
eRequestDTO .setEmail("test");
// rest of code for setting value
return eRequestDTO ;
}
ArgumentCaptor can be used to capture and Assert Arguments in your method. you can read about ArgumentCaptor here
Can someone help me writing JUnit for the below serviceImpl class
#Component
public class ProcessStatusMasterServiceImpl implements ProcessStatusMasterService {
#Autowired
private ProcessStatusRepository processStatusRepository;
#Autowired
private ApplicationContext applicationContext;
public ProcessAndMacroStatus findProcessMaster(StatusConstant statusConstants) {
ProcessStatusMasterService thisBean = (ProcessStatusMasterService)this.applicationContext.getBean(ProcessStatusMasterService.class);
List<ProcessAndMacroStatus> processStatuses = thisBean.findProcessMasterByCategory(statusConstants.getCategory());
Optional<ProcessAndMacroStatus> processStatusOpt = processStatuses.stream().filter(f -> f.getProcessAndMacroStatusKey().equals(statusConstants.getKey())).findFirst();
if (processStatusOpt.isPresent())
return processStatusOpt.get();
throw new IllegalArgumentException("Unable to find status: " + statusConstants.getKey() + " for category: " + statusConstants.getCategory());
}
#Cacheable({"ProcessStatusMasterCache"})
public List<ProcessAndMacroStatus> findProcessMasterByCategory(String category) {
List<ProcessAndMacroStatus> processStatuses = this.processStatusRepository.findByProcessMacroStatusCategory(category);
return processStatuses;
}
}
below is the code i am trying, but i am getting NPE for line when(thisBean.findProcessMasterByCategory(StatusConstant.GROUP_STATUS_SUCCESS.getCategory())).thenReturn(processStatuses);
Reason for this variable thisbean is null
#RunWith(MockitoJUnitRunner.class)
public class ProcessStatusMasterServiceImplTest {
#Mock
ProcessStatusRepository processStatusRepository;
#Mock
ApplicationContext applicationContext;
#InjectMocks
ProcessStatusMasterServiceImpl processStatusMasterServiceImpl;
#Test
public void findProcessMaster() throws Exception {
ProcessStatusMasterService thisBean = (ProcessStatusMasterService)this.applicationContext.getBean(ProcessStatusMasterService.class);
List<ProcessAndMacroStatus> processStatuses=new ArrayList<ProcessAndMacroStatus>();
when(thisBean.findProcessMasterByCategory(StatusConstant.GROUP_STATUS_SUCCESS.getCategory())).thenReturn(processStatuses);
processStatusMasterServiceImpl.findProcessMaster(StatusConstant.GROUP_STATUS_SUCCESS);
}
}
I think you're trying to mock the behaviour of the tested entity itself instead of the mocked dependencies. I'd try mocking it like this:
#Test
public void findProcessMaster() throws Exception {
List<ProcessAndMacroStatus> processStatuses=new ArrayList<ProcessAndMacroStatus>();
when(processStatusRepository.findProcessMasterByCategory(StatusConstant.GROUP_STATUS_SUCCESS.getCategory())).thenReturn(processStatuses);
processStatusMasterServiceImpl.findProcessMaster(StatusConstant.GROUP_STATUS_SUCCESS);
}
Please remove your thisBean in your production code, just use this. instead.
List<ProcessAndMacroStatus> processStatuses = this.findProcessMasterByCategory(statusConstants.getCategory());
and modify your test
#Test
public void findProcessMaster() throws Exception {
List<ProcessAndMacroStatus> processStatuses = new ArrayList<ProcessAndMacroStatus> ();
when(processStatusRepository.findProcessMasterByCategory(StatusConstant.GROUP_STATUS_SUCCESS.getCategory())).thenReturn(processStatuses);
processStatusMasterServiceImpl.findProcessMaster(StatusConstant.GROUP_STATUS_SUCCESS);
// your assert
}
I have enum like this
public enum NumbersJk {
ONE {
public void processCommand(Info Info) {
log.info("what is in process " + process)
process.add(Info);
}
},
TWO {
public void processCommand(Info Info) {
process.subtract(Info);
}
},
TEN {
public void processCommand(Info Info) {
process.divide(Info);
}
}
#Inject
private static ProcessNumber process;
public abstract void processCommand(Info Info) throws Exception;
}
It was injected using guice like this requestStaticInjection(NumbersJk.class);
public class AddNumbers {
public string testMethod(bla,bla,commandToExecute){
Info info = convert(bla,bla)
NumbersJk.valueOf(commandToExecute).processCommand(Info);
}
}
Now I am trying to write junit (powermockito) for this
Junit
#Mock
private ProcessNumber process = new ProcessNumber(new depsencey(), dependecny2());
#InjectMocks
AddNumber addNumber;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
#SneakyThrows
public void test() {
addNumber.testMethod(1,2,ONE)
}
This internally calls
NumbersJk.valueOf(commandToExecute).processCommand(Info);
And getting exception java.lang.NullPointerException: null
This is ProcessNumber is coming as null
log.info("what is in process " + process) printed as `what is in process null`
Question:
How to inject the class ProcessNumber in junit
Thanks
Jk
I figured it out.
We can use powermock to solve this problem Whitebox.setInternalState(NumbersJk.class, process);
Code:
#Mock
private ProcessNumber process = new ProcessNumber(new depsencey(), dependecny2());
#InjectMocks
AddNumber addNumber;
#Before
public void setUp() throws Exception {
Whitebox.setInternalState(NumbersJk.class, process);
MockitoAnnotations.initMocks(this);
}
#Test
#SneakyThrows
public void test() {
addNumber.testMethod(1,2,ONE)
}
I have created a mock test for testing inserting into a mongodb DB. I am wondering how I can verify my unit test. The method insert returns a void. So how can I verify? Also, some methods don't return void. How can I verify those as well?
#Repository
public class DataDao<T> implements {
#Autowired
private MongoOperations mongoOps;
public DataDao(MongoOperations mongoOps) {
this.mongoOps = mongoOps;
}
#Override
public void insert(Class<T> t, List<T> t1) {
this.mongoOps.insert(t1, t);
}
}
public class DataDaoTest {
#Mock
private DataDao<Data> daoMock;
public static List<Data> getData() {
// returns a list here
}
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testInsert() {
List<Data> data = getData();
daoMock.insert(Data.class, data);
}
}
Using the #Around annotation to define an aspect causes the autowiring of the bean to return null. I know this has something to do with some kind of proxy that aspectj sets up, and that this might be resolved via a few annotations. I just don't know what those annotations are, nor do I know whwere to put them. This only happens with the #Around aspects, not with #Before or #After.
#SpringBootApplication
public class AopStuffApplication implements CommandLineRunner{
#Autowired
private Business1 business1;
private static final Logger LOGGER = Logger.getLogger(AopStuffApplication.class.getName());
public AopStuffApplication() {}
public static void main(String[] args) {
SpringApplication.run(AopStuffApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
LOGGER.info(business1.calculateSomething());
}
}
#Service
public class Business1 {
#Autowired
private Dao1 dao1;
public String calculateSomething() {
return dao1.retrieveSomething();
}
}
#Repository
public class Dao1 {
public String retrieveSomething() {
System.out.println("Inside of retrieveSomething().");
return "Dao1";
}
}
#Aspect
#Component
public class MethodExecutionCalculationAspect {
private static final Logger LOGGER = Logger.getLogger(MethodExecutionCalculationAspect.class.getName());
#Around("execution(* com.training.AOPStuff.aopstuff.data.Dao1.retrieveSomething(..))")
public void trackElapsedTime(ProceedingJoinPoint proceedingJoinPoint) {
//start time
long startTime = System.currentTimeMillis();
//allow execution of method
try {
proceedingJoinPoint.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//end time
long elapsedTime = System.currentTimeMillis() - startTime;
System.out.println("message from within gthe aspect.");
//LOGGER.info("Elapsed time for " + proceedingJoinPoint + " was " + elapsedTime);
}
}