When use Spy and PowerMock together throws RuntimeException - junit

When I use Spy annotation together with the PowerMock in my JUnit test case, it throws RuntimeException, but when I use Mock annotation together with the PowerMock, the test case is working fine.
Anybody able to advise about my issue?
This is my code
#RunWith(PowerMockRunner.class)
#PrepareForTest({DBConnectionPool.class})
#PowerMockIgnore("javax.management.*")
public class TestAbcController {
private static final Logger logger = Logger.getLogger(TestAbcController .class.getName());
public TestAbcController () {
}
#Spy
private SampleDao mockDao;
#InjectMocks
private AbcController ctr;
private BasicDataSource ds = null;
private MockMvc mockMvc;
#BeforeClass
public static void setUpClass() {
logger.setLevel(Level.INFO);
PowerMockito.mockStatic(DBConnectionPool.class);
PowerMockito.when(DBConnectionPool.getDataSource()).thenReturn(UnitTestDbConnection.getDataSource());
}
#Test
public void testMain() {
when(mockDao.getMap()).thenReturn(new HashMap());
}
Below is the detail of the exception
java.lang.RuntimeException: Invoking the beforeTestMethod method on
PowerMock test listener
org.powermock.api.extension.listener.AnnotationEnabler#d86a6f failed.
at
org.powermock.api.mockito.internal.configuration.PowerMockitoSpyAnnotationEngine.process(PowerMockitoSpyAnnotationEngine.java:53)
at
org.powermock.api.mockito.internal.configuration.PowerMockitoInjectingAnnotationEngine.process(PowerMockitoInjectingAnnotationEngine.java:32)
at
org.powermock.api.extension.listener.AnnotationEnabler.injectSpiesAndInjectToSetters(AnnotationEnabler.java:60)
at
org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:55)
at
org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:90)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:292)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at
org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at
org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at
org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at
org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
at
org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at
org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
at
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)

I fixed this issue after I upgrade my mockito-core to 2.8.9 and powermock to 1.7.4

Related

Why code in not covered for verify in mokito?

This is the service file which has save method. This method is not covering in code coverage. These repository's noting but just a jpa repository's
#Service
public class ProcessFileService {
#Autowired
private ProcessFileRepository processFileRepository;
#Autowired
private ProcessRunRepository processRunRepository;
#Transactional
public void save(ProcessRun processRun, List<ProcessFile> processFiles) {
processRunRepository.save(processRun);
for (ProcessFile processFile : processFiles) {
processFile.setProcessRun(processRun);
processFileRepository.save(processFile);
}
}
}
This is the Test class and its done by verify()
#ExtendWith(MockitoExtension.class)
public class ProcessFileServiceTest {
#Mock
private ProcessFileRepository processFileRepository;
#Mock
private ProcessRunRepository processRunRepository;
#Test
void ProcessSave() {
ProcessRun processRun = new ProcessRun();
processRun.setEndDateTime("30/08/2022");
processRun.setNumFilesFailed(1L);
processRun.setNumFilesProcessed(1L);
processRun.setNumFilesTransferred(1L);
processRun.setStartDateTime("30/08/2022");
ProcessFile processFile = new ProcessFile();
processFile.setCurrentRetryAttempt(1);
processFile.setFileName("file.txt");
processFile.setSuccessfulYN(true);
processFile.setTransferDateTime("30/08/2022");
List<ProcessFile> processFiles = new ArrayList<ProcessFile>();
processFiles.add(processFile);
ProcessFileService processFileService = mock(ProcessFileService.class);
doNothing().when(processFileService).save(processRun, processFiles);
processFileService.save(processRun, processFiles);
verify(processFileService, times(1)).save(processRun, processFiles);
}
}
Please help me here what is i am missing here, i am new to junit.
You mocked your object under test, and in addition, stubbed method under test to do nothing (which by the way is the default behaviour for mocks).
You need to construct a proper instance of class under test, not mock it.
With MockitoExtension, a simple way to do this is:
#ExtendWith(MockitoExtension.class)
public class ProcessFileServiceTest {
#Mock
private ProcessFileRepository processFileRepository;
#Mock
private ProcessRunRepository processRunRepository;
#InjectMocks
ProcessFileService processFileService
...
}

How to verify an internal method call using Powermock?

I am trying to use PowerMockito to test a save method by verifying an internal audit() method call.
This internal call is made by auditor object which is being instantiated in an init() method of the class. As it is not injected I will not be able to mock it directly. When I used Mockito to verify it always said "There were zero interaction with the mock".
Question:How exactly do I test the save feature? Kindly help!
public class DaoImpl implements Dao{
private Auditor auditor;
#InjectValue
private ObjectLoader loader;
#InjectValue
private ConfigurationProvider confProvider;
#PostConstruct
public void init() {
//Mock this object instantiation and verify audit is called once
auditor = new SyncAuditor(confProvider.getClientConfiguration(), new EventRegProvider());
}
#Override
public void save(final AuditEvt auditEvt) {
final AuditedEvent auditedEvent = builder.build();
auditor.audit(auditedEvent);
}
Test :
#RunWith(PowerMockRunner.class)
#PrepareForTest({ DaoImplTest.class })
#PowerMockIgnore("javax.management.*")
public class DaoImplTest extends PowerMockito {
#InjectMocks
private DaoImpl dataAccess;
#Mock
private SynchAuditor auditorMock;
#Before
public void setUp() throws Exception {
loader = ObjectLoader.init("JUNIT");
loader.bind(ConfigurationProvider.class, configurationProviderMock);
dataAccess = loader.newInstance(DaoImpl.class);
}
#After
public void tearDown() {
loader.release(dataAccess);
ConnectionMgr.disconnect("JUNIT");
}
#Test
public void testSaveAuditEvent() throws Exception {
PowerMockito.whenNew(SynchAuditor.class).
withArguments(Matchers.any(ClientConfiguration.class), Matchers.any(EventRegProvider.class)).thenReturn(this.auditorMock);
final AuditEvent event = AuditEvent.from(null, "principal", UUID.randomUUID().toString(), "randomText",
new AuditEvtDefn((long) 522, "234242", "234242fdgd", true), SUCCESS, null, new GregorianCalendar());
dataAccess.save(event);
Mockito.verify(auditorMock, times(1)).audit(Matchers.any(AuditedEvent.class));
}
Even PowerMockito.verifyNew says there were zero interaction
PowerMockito.verifyNew(SynchronousAuditor.class,times(1)).withArguments(Matchers.any(AuditorClientConfiguration.class),Matchers.any(EventRegistrationProvider.class));
So, I figured out that java reflection will help in such a situation. You will have to get hold onto the real object and then set mocked object to it.
final Field privateAuditorField = DaoImpl.class.getDeclaredField("auditor");
privateAuditorField.setAccessible(true);
privateAuditorField.set(dataAccess, auditorMock);
Now verify will run sucessfully.
Mockito.verify(auditorMock, Mockito.times(1)).audit(Matchers.any(AuditedEvent.class));

Unable to autowire bean in Spring integration test

I am trying to autowire a bean for unit testing purpose.
I'm working with annotation based configuration classes and not using xml based application-context.
Porblem: It says Failed to load ApplicationContext
Here is my code.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = AppContextLoader.class, loader = AnnotationConfigContextLoader.class)
public class StockTest
{
static Logger logger = Logger.getLogger(StockTest.class);
#Autowired
private StockGenerator generator;
#Test
public void someTest()
{//some code here}
}
}
And my configuration class looks like this
#Configuration
public class AppContextLoader
{
#Bean
public StockGenerator stockProvider()
{
StockGenerator stock = new StockGenerator();
return stock;
}
}
Note: StockGenerator is spring managed so I am not sure how to handle it here. I am following this example.
Or is there any other way to autowire beans when one is not using xml based approach.

Multiple #Test method in a java class fails with java.lang.Exception: No runnable methods

I have multiple #Test method in a class while running the paxexam it fails with the below Exception
java.lang.Exception: No runnable methods
at org.junit.runners.BlockJUnit4ClassRunner.validateInstanceMethods(BlockJUnit4ClassRunner.java:169)
at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:104)
at org.junit.runners.ParentRunner.validate(ParentRunner.java:355)
at org.junit.runners.ParentRunner.<init>(ParentRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:57)
at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.<init>(ContainerTestRunner.java:54)
at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunnerBuilder.runnerForClass(ContainerTestRunnerBuilder.java:48)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunnerClassRequest.getRunner(ContainerTestRunnerClassRequest.java:61)
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:31)
at org.junit.runner.JUnitCore.run(JUnitCore.java:138)
The below is the pax exam code. When i run this code i get an exception. Adding one more point if i change this annotation #ExamReactorStrategy(PerClass.class) to #ExamReactorStrategy(PerMethod.class) this will work the problem is test container restarts after every method
#RunWith(PaxExam.class)
#ExamReactorStrategy(PerClass.class)
public class Integration5TestCases {
private static Logger LOG = LoggerFactory.getLogger(IntegrationTestCases.class);
#Inject
private BundleContext bc;
#Inject
protected FeaturesService featuresService;
/**
* To make sure the tests run only when the boot features are fully
* installed
*/
#Inject
BootFinished bootFinished;
#Configuration
public static Option[] configuration() throws Exception {
MavenUrlReference oracleLib = maven()
.groupId("com.oracle")
.artifactId("ojdbc6")
.version("11.2.0")
.type("jar");
MavenUrlReference dbHandler = maven().groupId("Oracle")
.artifactId("DBHandler")
.versionAsInProject()
.type("xml")
.classifier("features");
return new Option[] {
returnNewKarafInstance(),
systemProperty(PaxExamConstants.ORCALESYSPROPNAME).value(dbHandler.getURL()),
KarafDistributionOption.debugConfiguration("8898", true),
bootClasspathLibrary(oracleLib),
configureConsole().ignoreLocalConsole(),
logLevel(LogLevel.INFO),
keepRuntimeFolder(),
};
}
private static KarafDistributionBaseConfigurationOption returnNewKarafInstance(){
return karafDistributionConfiguration().frameworkUrl(maven().groupId("org.apache.karaf").artifactId("apache-karaf")
.type("zip").versionAsInProject())
.unpackDirectory(new File("target/paxexam/unpack/"))
.useDeployFolder(false);
}
#Inject
SessionFactory commandProcessor;
#Test
public void test1() throws Exception {
System.out.println("sd");
}
#Test
public void test2() throws Exception {
System.out.println("sd");
}
}
This was happening because junit lib was initialized twice inside the karaf container. Thanks for the help guys.

Creating Aspect bean in Spring Java Config file causes another bean to not be autowired

Having a weird issue with attempting to test a Spring AOP class.
Here is a similar setup since I cannot put the actual code on here.
Test Class:
#RunWith(SpringJUnit4ClassRunner.class)
#DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
#ContextConfiguration(classes = {MyTestConfiguration.class})
public class MyTest {
#Autowired
private MyService1 myService1;
#Autowired
private MyService2 myService2;
#Test
public void testAop() {
myService1.methodToBeIntercepted();
verify(myService2).create();
}
}
Spring Java Configuration File:
#EnableAspectJAutoProxy
#Configuration
public class MyTestConfiguration {
#Bean
public MyService1 myService1() {
return new MyService1Impl();
}
#Bean
public MyService2 myService2() {
return Mockito.mock(MyService2.class);
}
}
AOP Class:
#Aspect
#Component
public class MyAop {
#Autowired
private MyService2 myService2;
#Around("execution(* package.MyService1.methodToBeIntercepted(..))")
public void interception(ProceedingJoinPoint joinPoint) {
// do stuff
MyReturn myReturn = (MyReturn) joinPoint.proceed();
myService2.create();
}
}
With this setup I get an error saying that the test wanted 1 execution of myService2.create() but there was none. This means the AOP class is not intercepting the call properly and that the Spring configuration is correct in that all beans are found.
Next I added the following to MyTestConfiguration to create the bean for the AOP class:
#Bean
public MyAop myAop() {
return new MyAop();
}
Now I get a Spring error saying it can't find the MyService1 bean so the test never runs. Simply adding the myAop bean to MyTestConfiguration now causes the MyService1 bean to no longer be recognized by Spring.
Am I doing something wrong and if so, what?