Test with ExpectedException fails when using PoweMock with PowerMockRule - junit

I am trying to work with PowerMock, over Mockito; as I loved the API's for whennew() and verifyprivate() but i have some problem when trying to run testsuites with Categories TestRunner in Junit.
For using default JUnit test runners, I created a TestCase and added PowerMockRule as instance field with #Rule annotation. While execution of tests worked like this, ExpectedException TestRule is not working when used in conjunction
Example Code
#PowerMockIgnore ("*")
#PrepareForTest (CustomizedSSHConnection.class)
public class TestExpectedExceptionRule {
private Connection connection;
private ConnectionInfo connectionInfo;
#Rule
public PowerMockRule rule = new PowerMockRule ();
#Rule
public ExpectedException exception = ExpectedException.none ();
#Test
public void testExcepitonWithPowerMockRule() {
exception.expect (NullPointerException.class);
exception.expectMessage ("Image is null");
throw new NullPointerException ("Image is null");
}
}
Instead of using #Rule PowerMockRule if I use #RunWith(PowerMockRunner.class) this testcase will pass.
One other observation is if I annotate PowerMockRule with #ClassRule this succeeds but some of the mocking methods throwing exceptions.

PowerMock creates a deep clone of the TestExpectedExceptionRule object. Because of this it is running the test with a new ExpectedException rule, but you're calling exception.expect (NullPointerException.class) on the original rule. Hence the test fails, because the clone of the ExpectedException rule doesn't expect an exception.
Nevertheless there are at least two solutions for your problem.
RuleChain
Order the rules with JUnit's RuleChain. This needs some additional ugly code, but it works.
private ExpectedException exception = ExpectedException.none ();
private PowerMockRule powerMockRule = new PowerMockRule();
#Rule
public TestRule ruleChain = RuleChain.outerRule(new TestRule() {
#Override
public Statement apply(Statement base, Description description) {
return powerMockRule.apply(base, null, description);
}
}).around(exception);
Fishbowl
If you are using Java 8 then you can replace the ExpectedException rule with the Fishbowl library.
#Test
public void testExcepitonWithPowerMockRule() {
Throwable exception = exceptionThrownBy(
() -> throw new NullPointerException ("Image is null"));
assertEquals(NullPointerException.class, exception.getClass());
assertEquals("Image is null", exception.getMessage());
}
Without Java 8, you have to use an anonymous class.
#Test
public void fooTest() {
Throwable exception = exceptionThrownBy(new Statement() {
public void evaluate() throws Throwable {
throw new NullPointerException ("Image is null");
}
});
assertEquals(NullPointerException.class, exception.getClass());
assertEquals("Image is null", exception.getMessage());
}

I was able to fix this using the expected attribute in the #Test annotation. But the problem with this approach is that am unable to assert the exception message. Which is fine for me for now.
#PowerMockIgnore ("*")
#PrepareForTest (CustomizedSSHConnection.class)
public class TestExpectedExceptionRule {
private Connection connection;
private ConnectionInfo connectionInfo;
#Rule
public PowerMockRule rule = new PowerMockRule ();
#Rule
public ExpectedException exception = ExpectedException.none ();
#Test(expected = NullPointerException.class)
public void testExcepitonWithPowerMockRule() {
throw new NullPointerException ("Image is null");
}
}

I solved this problem by creating a PowerMockTestUtil class that uses a FunctionalInterface.
Utility class:
/**
* Utility class to provide some testing functionality that doesn't play well with Powermock out
* of the box. For example, #Rule doesn't work well with Powermock.
*/
public class PowerMockTestUtil {
public static void expectException(RunnableWithExceptions function, Class expectedClass, String expectedMessage) {
try {
function.run();
fail("Test did not generate expected exception of type " + expectedClass.getSimpleName());
} catch (Exception e) {
assertTrue(e.getClass().isAssignableFrom(expectedClass));
assertEquals(expectedMessage, e.getMessage());
}
}
#FunctionalInterface
public interface RunnableWithExceptions<E extends Exception> {
void run() throws E;
}
}
Sample test:
#Test
public void testValidateMissingQuantityForNewItem() throws Exception {
...
expectException(() -> catalogEntryAssociationImporter.validate(line),
ImportValidationException.class,
"Quantity is required for new associations");
}

Related

mockito simulate test exception thrown by service

I am trying to test exception thrown from service when I use the instance of it.
Like I am trying to use Imock in Trans.class and use IMock method.
Below is the code
public class MockImpl implements IMock{
public String external(String str) throws Exception {
if(str.equals("throw")){
throw new Exception("Thrown exception.");
}
return str;
}
}
public class Trans {
private IMock mc;
public static int failed;
public String performTrans(String str) throws Exception {
return call(str);
}
private String call(String str) throws Exception {
mc = new MockImpl();
try {
return mc.external(str);
}
catch(Exception e){
failed++;
throw e;
}
}
}
In test class I am trying to do this
public class TestMock {
#Test
public void testMock() throws Exception {
Trans trans = mock(Trans.class);
IMock iMock = mock(IMock.class);
doThrow(new Exception()).when(iMock).external(any(String.class));
for(int i =0;i<10 ;i++){
trans.performTrans("any");
}
System.out.println(Trans.failed);
assertEquals(9, Trans.failed);
}
}
As I am new to this, I am not sure if my understanding is correct, what I am trying to achieve is
When I do # Trans.performTrans(String);
Then doThrow(new Exception()).when(iMock).external(any(String.class)); should happen. How can I tell Mockito or any test framework that The exception should be thrown should be simulated from the Imock service method, even if it is indirectly called.
UPDATE
After trying to test this way
#RunWith(MockitoJUnitRunner.class)
public class TestMock {
#Test
public void testMock() throws Exception {
Trans trans = new Trans();
IMock iMock = mock(IMock.class);
trans.setInter(iMock);
//doThrow(new Exception()).when(iMock).external(any(String.class));
trans.performTrans("abc");
verify(iMock).external(new String("a"));
System.out.println(Trans.failed);
assertEquals(9, Trans.failed);
}
}
I get this error.
Wanted but not invoked: iMock.external("a");
-> at com.app.TestMock.testMock(TestMock.java:32) Actually, there were zero interactions with this mock.
what could be wrong?

How do you test exceptions using mockito in RCP Application?

I have the following code in my performFinish() method of my Wizard Class :
public boolean performFinish() {
try {
getContainer().run(true, false, changeArtifactRunnable());
}
catch (InvocationTargetException | InterruptedException e) {
LoggerClass.logException(e);
}
I want to test Exception for InvocationTargetException and InterruptedException using Mockito.
In the above code, getContainer() method is from org.eclipse.jface.wizard.Wizard class and
public void run(boolean fork, boolean cancelable,
IRunnableWithProgress runnable) throws InvocationTargetException,
InterruptedException;
method is from org.eclipse.jface.operation.IRunnableContext class.
How do I test both the exceptions in performFinish() method?
You can use the expected keyword in order to do so. For example:
#Test(expected = InvocationTargetException.class)
public void testInvocationTargetException() {
\\Invoke the method to be tested under the conditions, such that InvocationTargetException is thrown by it. No need of any assert statements
}
===========================================================================
Edit:
#RunWith(MockitoJUnitRunner.class)
public class EditArtifactWizardTest {
#Spy
//use correct constructor of EditArtifactWizard
private EditArtifactWizard editArtifactWizardSpy=Mockito.spy(new EditArtifactWizard ());
#Test(expected = InvocationTargetException.class)
public void testInvocationTargetException() {
\\Invoke the method to be tested under the conditions, such that InvocationTargetException is thrown by it. No need of any assert statements
Mockito.when(editArtifactWizardSpy.getContainer()).thenThrow(InvocationTargetException.class);
editArtifactWizardSpy.performFinish();
}
}
You can create the Spy of EditArtifactWizard class and mock the behavior of the getContainerMethod.
P.S: Please excuse for typos or compilation error as I am not using any editor.

Can any one help me in mocking a static method which returns an object, and this static method is present in a final class

I need help for below thing,
I have to write a Junit using PowerMock/Mockito for a method which makes a call to a static method of a final class present in an external jar.
The method for which i need to write the JUnit test is:
public class SomeClass {
private PrivateKey privateKeyFromPkcs8(String privateKeyPem) throws IOException {
Reader reader = new StringReader(privateKeyPem);
Section section = PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY");
if (section == null) {
throw new IOException("Invalid PKCS8 data.");
}
byte[] bytes = section.getBase64DecodedBytes();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
try {
KeyFactory keyFactory = SecurityUtils.getRsaKeyFactory();
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
} catch (NoSuchAlgorithmException exception) {
} catch (InvalidKeySpecException exception) {
}
throw new IOException("Unexpected exception reading PKCS data");
}
}
In the above code PemReader is a final class and readFirstSectionAndClose(reader, "PRIVATE KEY") is a static method in PemReader.
I have tried writing the test shown below but Section object(section) is showing as null while debugging. Perhaps the actual code (PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY")) is getting called instead of the mock.
#RunWith(PowerMockRunner.class)
#PrepareForTest({SomeClass.class,PemReader.class})
public class SomeClassTest {
#InjectMocks
SomeClass mockSomeClass;
#Mock
private Reader mockReader;
#Mock
private Section mockSection;
#Test
public void testPrivateKeyFromPkcs8() throws Exception {
PowerMockito.mockStatic(PemReader.class);
Mockito.when(PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY")).thenReturn(mockSection);
assertNotNull(mockSomeClass.privateKeyFromPkcs8(dummyPrivateKey));
}
}
Please help me in writing a Junit using powermockito/mockito
You have to prepare the final, static class.
Here's an example using the PowerMock annotations for JUnit:
#RunWith(PowerMockRunner.class)
#PrepareForTest({PemReader.class})
public class PemReaderTest {
#Mock
private Reader mockReader;
#Mock
private Section mockSection;
#Test
public void testMockingStatic() {
PowerMockito.mockStatic(PemReader.class);
Mockito.when(PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY")).thenReturn(mockSection);
Assert.assertEquals(mockSection, PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY"));
}
}
For completeness, here's the definition of PemReader:
public final class PemReader {
public static Section readFirstSectionAndClose(Reader reader, String key) {
return null;
}
}
The above test passes with the following versions:
JUnit: 4.12
Mockito: 2.7.19
PowerMock: 1.7.0
Update 1: based on your updated question. Your test case will pass (or at least the invocation on PemReader.readFirstSectionAndClose will return something) if you just make this change:
Mockito.when(PemReader.readFirstSectionAndClose(
Mockito.any(Reader.class),
Mockito.eq("PRIVATE KEY"))
).thenReturn(mockSection);
The version of this instruction in your current test case relies on equality matching between the StringReader which your code passes into readFirstSectionAndClose and the mocked Reader which your test case supplies. These are not 'equal' hence the mocked invocation's expectations are not met and your mockSection is not returned.
A few, unrelated, notes:
There is no need to include SomeClass.class in #PrepareForTest, you only need to include the classes which you want to mock in that annotation, since SomeClass is the class you are trying to test there is no mocking required for that class.
Using #InjectMocks to instance SomeClass is a bit odd, since SomeClass has no (mockito provided) mocks to inject into it :) you can replace this declaration with SomeClass someClass = new SomeClass();
In the code you supplied SomeClass.privateKeyFromPkcs8 has private scope so it cannot be tested (or called in any way) from SomeClassTest.

ClientResponse Failure in mockito test cases

Iam working on mockito testcases positive test methods are getting executed but comming to Exception Test methods its failing with the Exception
java.lang.Exception: Unexpected exception, expected<com.apple.ist.retail.xcard.common.exception.InvalidArgumentException> but was<org.jboss.resteasy.client.ClientResponseFailure>
at
Below is the test method which is failing and its parent class containing client object
package com.apple.ist.retail.xcard.ws.exception;
public class TestActivatePrepaidCard extends CertificateResourceTestCase {
public TestActivatePrepaidCard(String aMediaType) {
super(aMediaType);
}
#Before
public void setUp() {
super.setUp();
}
#Test(expected = InvalidArgumentException.class)
public void testActivatePrepaidCard_InvalidArgumentException()
throws DuplicateCertificateIDException, InvalidArgumentException,
DupTxnRefException, AmountException, SystemException,
XCardException {
when(
server.activatePrepaidCard(any(DiagnosticContext.class),
any(String.class), any(Number.class),
any(Amount.class), any(String.class), any(int.class),
any(HashMap.class), any(String.class),
any(SalesOrg.class), any(TxnRef.class))).thenThrow(
new InvalidArgumentException("Invalid Argument ",
INVALID_ARGUMENT));
client.activatePrepaidCard(certificateRequest);
}
Its failing near client.activatePrepaidCard(certificateRequest); with ClientResponseFailure Exception
Parent test case is
package com.apple.ist.retail.xcard.ws.exception;
#RunWith(value = Parameterized.class)
public abstract class CertificateResourceTestCase extends Assert {
protected CertificateResource client;
protected XCardServiceServer server;
protected CertificateResource resource;
protected CertificateRequest certificateRequest;
// protected Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
private String mediaType;
public CertificateResourceTestCase(String aMediaType) {
this.mediaType = aMediaType;
server = mock(XCardServiceServer.class);
CertificateResourceImpl xcardServiceRs = new CertificateResourceImpl();
xcardServiceRs.setService(server);
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addSingletonResource(xcardServiceRs);
dispatcher.getProviderFactory().addExceptionMapper(
XCardExceptionMapper.class);
dispatcher.getProviderFactory().addExceptionMapper(
BusinessExceptionMapper.class);
dispatcher.getProviderFactory().addExceptionMapper(
RuntimeExceptionMapper.class);
dispatcher.getProviderFactory().addExceptionMapper(
BusinessExceptionMapper.class);
dispatcher.getProviderFactory().addExceptionMapper(
RuntimeExceptionMapper.class);
dispatcher.getProviderFactory()
.getServerMessageBodyWriterInterceptorRegistry()
.register(new XCardTxnWriterInterceptor());
dispatcher.getProviderFactory().getContextDataMap()
.put(HttpServletRequest.class, new MockHttpServletRequest());
client = ProxyFactory.create(CertificateResource.class, "/", new InMemoryClientExecutor(dispatcher));
diagnosticContext.setReportingRecommended(false);
}
#After
public void tearDown() throws Exception {
Mockito.reset(server);
}
Please let me know whats wrong in my code,I am pasting complete code so that I will not miss any detail
Your code is throwing an ClientResponseFailure. Debug your test and find out why. Use an exception breakpoint.

JMock triggers AssertionError: invokation expected once, never invoked - but it has been invoked

I'm pretty new to programming with java but I've tried to directly start with unit-testing and therefore also used JMock. I have already implemented some test-cases (with JMock) that work, but this one I just can't get to run.
What I did:
I wrote a test-class which creates a mock object and then I'm expectation one (using oneOf) invocation. After running the unit test it says it fails (but the logs say otherwise, as i print out the data I returned at the invocation using will(returnValue(x)).
The next funny/weird thing is - if I change the oneOf to "never" the unit test succeeds, but it throws an Exception:
Exception in thread "Thread-2" java.lang.AssertionError: unexpected invocation: blockingQueue.take()
expectations:
expected never, never invoked: blockingQueue.take(); returns
what happened before this: nothing!
Here the code:
#RunWith(JMock.class)
public class ExecuteGameRunnableTest {
private Mockery context = new JUnit4Mockery();
private Thread testObject;
private BlockingQueue<Game> queueMock;
private Executor executorMock;
#SuppressWarnings("unchecked")
#Before
public void setUp() {
queueMock = context.mock(BlockingQueue.class);
executorMock = context.mock(Executor.class);
testObject = new Thread(new ExecuteGameRunnable(queueMock, executorMock, true));
}
#After
public void tearDown() {
queueMock = null;
executorMock = null;
testObject = null;
}
#Test
public void testQueueTake() throws InterruptedException {
final Game game = new Game();
game.setId(1);
game.setProcessing(false);
context.checking(new Expectations() {{
never(queueMock).take(); will(returnValue(game));
}});
testObject.start();
context.assertIsSatisfied();
}
}
and the runnable that I'm testing:
public class ExecuteGameRunnable implements Runnable {
private BlockingQueue<Game> queue;
private Executor executor;
private Boolean unitTesting = false;
static Logger logger = Logger.getLogger(ExecuteGameRunnable.class);
public ExecuteGameRunnable(BlockingQueue<Game> queue, Executor executor) {
this.queue = queue;
this.executor = executor;
}
public ExecuteGameRunnable (BlockingQueue<Game> queue, Executor executor, Boolean unitTesting) {
this(queue,executor);
this.unitTesting = unitTesting;
}
public void run() {
try {
do {
if (Thread.interrupted()) throw new InterruptedException();
Game game = queue.take();
logger.info("Game "+game.getId()+" taken. Checking if it is processing"); // THIS ONE PRINTS OUT THE GAME ID THAT I RETURN WITH JMOCK-FRAMEWORK
if (game.isProcessing()) {
continue;
}
game.updateProcessing(true);
executor.execute(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
} while (!unitTesting);
} catch (InterruptedException ex) {
logger.info("Game-Execution-Executor interrupted.");
return;
} catch (DataSourceException ex) {
logger.fatal("Unable to connect to DB whilst executing game: "+id_game,ex);
return;
}
}
}
JMock isn't thread safe. It's intended to support unit testing, rather than what is a very small integration test. Frankly, in this case I'd use a real BlockingQueue rather than a mock one. And there is no way you should have a unitTesting flag in your production code.
One more thing, you don't need to set the fields in the test class to null, jUnit flushes the instance for every test.