I have a Class under Test that looks like this:
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.activerecord.RooJpaActiveRecord;
#RooJavaBean
#RooJpaActiveRecord(table="test_class", finders={ "findById" })
public class TestClass {
boolean test;
public static String returnSomething() {
return "X";
}
}
As you can see, it has Roo-Annotations and a static method I need to mock.
My test uses the (mocked) static method and also creates new objects from this class.
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(TestClass.class)
#PowerMockIgnore("javax.management.*")
public class PowerMockitoTest {
#Test
public void test() {
PowerMockito.mockStatic(TestClass.class);
PowerMockito.when(TestClass.returnSomething()).thenReturn("Y");
Assert.assertEquals("Y", TestClass.returnSomething());
TestClass x = new TestClass();
}
}
The call to new TestClass() gives me the following Exception:
java.lang.NullPointerException
at org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.ajc$if$bb0(AnnotationBeanConfigurerAspect.aj:1)
at ....TestClass.<init>(TestClass.java:8)
and when I debug into the AnnotationBeanConfigurerAspect class I can see that the Configurable passed into this method is indeed null
public static final boolean ajc$if$bb0(Configurable c) {
return c.preConstruction();
}
Is this a bug in Powermock?
Are there any workarounds?
Versions used:
[INFO] +- junit:junit:jar:4.11:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.mockito:mockito-all:jar:1.9.5:test
[INFO] +- org.powermock:powermock-module-junit4:jar:1.5.3:test
[INFO] | \- org.powermock:powermock-module-junit4-common:jar:1.5.3:test
[INFO] | \- org.powermock:powermock-reflect:jar:1.5.3:test
[INFO] +- org.powermock:powermock-api-mockito:jar:1.5.3:test
[INFO] | \- org.powermock:powermock-api-support:jar:1.5.3:test
[INFO] +- org.powermock:powermock-module-junit4-rule:jar:1.5.1:test
[INFO] | +- org.powermock:powermock-classloading-base:jar:1.5.1:test
[INFO] | \- org.powermock:powermock-core:jar:1.5.1:test
[INFO] \- org.powermock:powermock-classloading-xstream:jar:1.5.1:test
Of course, this is not true, but well: PowerMock is a bug. The second you start using it you have to be prepared to spent a lot of time on such issues.
Especially when you start mixing power mock ... with another library that does byte code manipulation. That is simply calling for trouble.
So, the only answer that you will benefit from in the long run: don't do it. Do not use PowerMock.
Instead: understand that each and every situation that requires for PowerMock to enable testing (like static method calls) wants to tell you: "your design is bad, go fix it".
And if you really encounter situations that don't allow for design changes, then you might still prefer to not use PowerMock; worst case consider writing some real "functional" tests for that corner - just to avoid situations as the one you are facing right now.
I had similar problem in my code. Unfortunately I had to mock behavior of inner component, something like this:
public class LockWithRequestTimeout implements ReadWriteLock
//...
#TracePerformance // ----> this annotation somehow influence PowerMockito
#Override
public void lock()
{
try
{
while (!l.tryLock(1, TimeUnit.SECONDS))
{
PerformanceAdvice.checkRequestTimeout(() -> toString()); // ----> this is what i wanted to mock, PerformanceAdvice is AOP that handles TracePerformance annotation
}
}
catch (final InterruptedException e)
{
final String msg = "interrupted while waiting for " + this;
LogFactory.getLog(LockWithRequestTimeout.class).warn(msg);
Thread.currentThread().interrupt();
throw new RuntimeException(msg, e);
}
}
//...
My first thought was to mock PerformanceAdvice checkRequestTimeout method, but it behaved like in your example, I got NullPointerException.
My solution was to make small refactoring, I have extracted new method:
protected static void checkRequestTimeout(final Supplier<String> msg)
{
PerformanceAdvice.checkRequestTimeout(msg);
}
and instead of mocking PerformanceAdvice I mocked this new method in class LockWithRequestTimeout.
My proposition for you is to extract method
public static String returnSomething() {
return "X";
}
and move it to some kind of Utils? To other class that is not annotated by Roo
I filed a bug and provided a fix:
https://github.com/jayway/powermock/issues/676
Related
I am using Junit 3.8.1 and updated Jmokit to 1.49
I have a project in which existing tests present with MockUp. Having private methods mocked. After updating Jmockit jar to 1.49 version getting error as follows
java.lang.IllegalArgumentException: Unsupported fake for private method
My Java class to test is
public class Foo {
String aVar;
public Foo(String str) {
aVar = str;
}
private void concatStr(String append) {
aVar = aVar.concat(append);
}
public void doSomeTask() {
concatStr("Test");
}
}
and test class is
public class FooTest extends TestCase {
public FooTest(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(FooTest.class);
}
public void test() {
new MockUp<Foo>() {
#Mock
private void concatStr(String append) {
Assert.assertEquals("Test", append);
}
};
Foo foo = new Foo("demoString");
foo.doSomeTask();
}
}
On console getting error as below
[INFO] Running org.test.jmokitupdate.FooTest
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.028 s <<< FAILURE! - in
org.test.jmokitupdate.FooTest
[ERROR] test(org.test.jmokitupdate.FooTest) Time elapsed: 0.025 s <<< ERROR!
java.lang.IllegalArgumentException: Unsupported fake for private method
Foo#concatStr(Ljava/lang/String;)V found
at mockit.internal.faking.FakedClassModifier.visitMethod(FakedClassModifier.java:96)
at mockit.asm.methods.MethodReader.readMethodBody(MethodReader.java:118)
at mockit.asm.methods.MethodReader.readMethod(MethodReader.java:75)
at mockit.asm.methods.MethodReader.readMethods(MethodReader.java:62)
at mockit.asm.classes.ClassReader.readFieldsAndMethods(ClassReader.java:196)
at mockit.asm.classes.ClassReader.accept(ClassReader.java:89)
at mockit.internal.faking.FakeClassSetup.modifyRealClass(FakeClassSetup.java:80)
at mockit.internal.faking.FakeClassSetup.redefineMethods(FakeClassSetup.java:61)
at mockit.MockUp.redefineClass(MockUp.java:114)
at mockit.MockUp.<init>(MockUp.java:78)
at org.test.jmokitupdate.FooTest$1.<init>(FooTest.java:31)
at org.test.jmokitupdate.FooTest.test(FooTest.java:31)
Earlier versions of JMockit allowed mocking private methods, and honestly, I thought it was a brilliant differentiator with other mocking-frameworks. Sadly, more recent versions have eliminated the ability to mock privates - became a warning in 1.45 and an exception in 1.47.
There is no real official explanation, although supposition is that private methods should be so simple they do not need testing/mocking. By extension, if you are trying to access it for purposes of testing, then it should not be private. People (other than you) would likely want to also alter the behavior, and that your need to access it for test purposes is strongly suggesting the method ought to be accessible. Make it protected or package-private. FWIW, there are annotations like "#VisibleForTesting" that can be used to help indicate the intent.
So you know, 1.47 also removed the "Deencapsulation" mechanism which was one of my favorite tools for inspecting/setting private data. Painful at the time I had to convert, because it littered my test code, but in hind sight, #Tested/#Injectable (the replacement) is way cleaner. As the maintainer indicates, JMockit is not intended as a way to get at privates, there are other frameworks that do that and no sense in doing the job that they do better. I switched over to Apache's commons-lang3 (FieldUtils/MethodUtils/etc), but other frameworks exist
Preface: I'm fairly new to Camel, and after digesting Camel in action as best as possible, I'm adapting it to a project I'm on. In this project, we have some rather complex error handling, and I want to make sure I can replicate this as we Camel-ize our code.
On our project (as most) there are a set of Exceptions we want to retry and a set that we don't - but more specifically, there are a set that we want to retry more than others (not all recoverable errors can be treated the same). In this case, I was attempting to define an onException block to change the redelivery policy. However, it seems that the Exchange maintains the count (Exchange.REDELIVERY_COUNTER) and that this count is not dependent on which exception is thrown. Is there a way to make this count be specific for a given exception?
For example - I have two exceptions FooException and BarException. In my route (or really in the whole context), I want to retry FooExceptions 10 times, but BarExceptions should only retry 2 times. So the context will contain:
<onException>
<exception>my.exception.FooException</exception>
<redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000"
</onException>
<onException>
<exception>my.exception.BarException</exception>
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000"
</onException>
Now, the concern - if my application throws a FooException and retries 4 times (each time throwing a FooException) and then on the 5th attempt, it throws a BarException, it seems that the way this works is the Exchange will have a REDELIVERY_COUNTER of 5, and when I reset the policy to only try twice, it (logically) concludes that the route should not be retried and throws the exception back out. However, in my application BarExceptions should be retried twice, regardless of how many FooExceptions get thrown. And likewise, if it alternates throwing Foo and Bar exceptions, I would like it to only increment the counter for the given exception.
The very end of Camel in Action promotes using a retryWhile - is this the only way to grab the kind of control I'm looking for? Do I need to create a stateful bean that is aware of the count per exception? Or am I overlooking something simple? I want to make sure that as I approach this refactor I don't start us off on an ugly path.
Using Camel 2.10.1
I checked your case with following test:
import org.apache.camel.EndpointInject;
import org.apache.camel.Exchange;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
import java.util.concurrent.atomic.AtomicLong;
/**
* #author Illarion Kovalchuk
* Date: 12/7/12
* Time: 2:58 PM
*/
public class Test extends CamelTestSupport
{
private static final String MIDDLE_QUEUE = "seda:middle";
#EndpointInject(uri = "mock:result")
protected MockEndpoint resultEndpoint;
#Produce(uri = "direct:start")
protected ProducerTemplate template;
private Processor processor = new Processor();
#Test
public void shouldRedeliverOnErrors() throws Exception
{
resultEndpoint.expectedBodiesReceived("Body");
template.sendBodyAndHeader(MIDDLE_QUEUE, "Body", "Header", "HV");
resultEndpoint.assertIsNotSatisfied();
}
#Override
protected RouteBuilder createRouteBuilder()
{
return new RouteBuilder()
{
#Override
public void configure() throws Exception
{
onException(FooException.class)
.redeliveryDelay(2000)
.maximumRedeliveries(10);
onException(BarException.class)
.redeliveryDelay(5000)
.maximumRedeliveries(2);
from(MIDDLE_QUEUE)
.bean(Processor.class, "process")
.to(resultEndpoint)
.end();
}
};
}
public static class Processor
{
private static AtomicLong retryState = new AtomicLong(0L);
public static void process(Exchange e) throws FooException, BarException
{
long rs = retryState.getAndAdd(1L);
if (rs < 4)
{
System.err.println("Foo Attempt "+ rs);
throw new FooException();
}
if (rs == 4)
{
System.err.println("Bar Attempt "+ rs);
throw new BarException();
}
System.err.println("Normal Attempt "+ rs);
}
}
public static class FooException extends Throwable
{
}
private static class BarException extends Throwable
{
}
}
As the result, your concirn was approved: delivery attempts gets exhausted after BarException, even if we have only 4 FooExceptions and 1 BarException.
Unfortunately I can't answer your question fully right now, but I am digging into it and will updated my unswer if get something new.
Try to replace the order you define your exceptions, e.g.:
<onException>
<exception>my.exception.BarException</exception>
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000"
</onException>
<onException>
<exception>my.exception.FooException</exception>
<redeliveryPolicy maximumRedeliveries="10" redeliveryDelay="2000"
</onException>
I'm throwing an exception MyCustomException from my application. (EJB Layer)
I've an exception mapper in web service layer which looks like following -
package net.webservices;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import net.common.MyCustomException;
#Provider
public class EJBExceptionMapper implements
ExceptionMapper<net.common.MyCustomException> {
public Response toResponse(MyCustomException exception) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
I've registered my mapper in web.xml of the web service layer as following -
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>net.webservices.EJBExceptionMapper</param-value>
</context-param>
The EJBExceptionMapper is not catching the MyCustomException. But instead its being caught by the catch block of the web service implementation.
What could be the problem?
Note: I don't want to register my ExceptionMapper manually using getProviderFactory().addExceptionMapper()
I don't know why your solution doesn't work (but I've never used RESTeasy, only Jersey). In any case, it would probably be simpler to extend WebApplicationException. That way, you don't have to register a provider:
public class MyCustomException extends WebApplicationException {
public MyCustomException() {
super(Response.status(Response.Status.BAD_REQUEST).build());
}
}
You need to throw exception (of type MyCustomException ) in the catch block and add a "Throws MyCustomException" to the method signature
I'd like to be able to use JUnit 4.7's ExpectedException #Rule in Scala. However, it doesn't seem to catch anything:
import org.junit._
class ExceptionsHappen {
#Rule
def thrown = rules.ExpectedException.none
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
This still fails with a NumberFormatException.
To make this work with JUnit 4.11 in Scala, you should meta-annotate your annotation so that the annotation is applied only to the (synthetic) getter method, not the underlying field:
import org.junit._
import scala.annotation.meta.getter
class ExceptionsHappen {
#(Rule #getter)
var thrown = rules.ExpectedException.none
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
EDIT: Following the release of JUnit 4.11, you can now annotate a method with #Rule.
You will use it like:
private TemporaryFolder folder = new TemporaryFolder();
#Rule
public TemporaryFolder getFolder() {
return folder;
}
For earlier versions of JUnit, see the answer below.
--
No, you can't use this directly from Scala. The field needs to be public and non-static. From
org.junit.Rule:
public #interface Rule: Annotates fields that contain rules. Such a field must be public, not static, and a subtype of TestRule.
You cannot declare a public fields in Scala. All fields are private, and made accessible by accessors. See the answer to this question.
As well as this, there is already an enhancement request for junit (still Open):
Extend rules to support #Rule public MethodRule someRule() { return new SomeRule(); }
The other option is that it non-public fields be allowed, but this has already been rejected: Allow #Rule annotation on non-public fields.
So your options are:
clone junit, and implement the first suggestion, the method, and submit a pull request
Extend the Scala class from a java class which implements the #Rule
-
public class ExpectedExceptionTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
}
and then inheriting from that:
class ExceptionsHappen extends ExpectedExceptionTest {
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
which works correctly.
As a very newbie to Scala I am just using a very simple workaround: explicitly catch the exception and fail if your expected exception is not thrown.
Below is a sample skeleton:
try {
*your code that should throw an exception*
fail("Did not generate *the.Exception.you.expect*")
} catch {
case t: *the.Exception.you.expect* => // do nothing, it's expected :)
}
Without knowing JUnit rules, and without testing it, because I don't have an appropriate setup at hand, I go out on a limb and suggest turning thrown into a val.
I guess its some member that is initialized with something and then it gets some state and then some other machinery checks the state against something. You are always creating new ones and keep forgetting the expectation.
If Scala has something similar like static imports, then catch-exception is an alternative to JUnit 4.7's ExpectedException #Rule.
I'm still using JUnit 4, and found #Juh_'s comment instructive. This worked in Scala 2.11.0.
import org.junit.rules.ExpectedException
import org.junit.{Rule, Test}
import scala.reflect.{ClassTag, classTag}
class DeleteMe {
object Thrower {
def throwException[R <: Throwable: ClassTag](message: String): Unit = {
throw classTag[R].runtimeClass.getConstructor(classOf[String]).newInstance(message).asInstanceOf[R]
}
}
#Rule
def exceptionRule:ExpectedException = ExpectedException.none()
#Test(expected = classOf[Exception])
def checkConversionExceptions = {
val myMessage = "My Message"
exceptionRule.expectMessage(myMessage)
Thrower.throwException[Exception](myMessage)
()
}
}
To tell you first, i have tried and tried it again and now i need some help
Heres my code
package staticPkg;
public class Static {
public static final String staticMethod() {
System.out.println("Static method called");
return "Static called";
}
}
package staticPkg;
public class TargetClass {
Static staticClass;
public String callHere() {
return Static.staticMethod();
}
}
package staticPkg;
import org.easymock.EasyMock;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
#PrepareForTest({Static.class})
public class TestClass {
Static staticClass = null;
#ObjectFactory
public IObjectFactory getObjectFactory() {
System.out.println("got object factory");
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
#BeforeMethod
public void setup() {
System.out.println("print me");
PowerMock.mockStatic(Static.class);
staticClass = PowerMock.createMock(Static.class);
}
#Test
public void testMe() {
EasyMock.expect(Static.staticMethod()).andReturn("Mock called").anyTimes();
PowerMock.replay(Static.class,staticClass);
TargetClass tc = new TargetClass();
String output = tc.callHere();
PowerMock.verify(Static.class,staticClass);
System.out.println(output);
}
}
And heres the log
[Parser] Running:
C:\MockWorkspace\Mock\temp-testng-customsuite.xml
got object factory
print me
Static method called
FAILED: testMe
java.lang.IllegalStateException: no last call on a mock available
at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521)
at org.easymock.EasyMock.expect(EasyMock.java:499)
at staticPkg.TestClass.testMe(TestClass.java:46)
... Removed 22 stack frames
===============================================
staticPkg.TestClass
Tests run: 1, Failures: 1, Skips: 0
===============================================
===============================================
Mock
Total tests run: 1, Failures: 1, Skips: 0
===============================================
Help please, i have tried a variety of solutions, can't get it done.
Please can anyone try this code and correct it for success?
I get error in EasyMock.expect ...............
Got a work around at http://blogs.bytecode.com.au/glen/2006/10/12/doing-bytecode-kungfu-with-javassist.html
And it works
But wait..........I am stuck again
My testcase works fine when runs alone, but when run with Ant, it gives problem. Might be other test cases of different files are interfering.
I got the same error, when my individual test case was using #PrepareTest & easymock/powermock
[testng] ====================STATIC CALLED===========================
[testng] javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClass
Loader): attempted duplicate class definition for name: "com/symantec/mobius/aggregator/submission/SubmissionFactory"
[testng] at javassist.ClassPool.toClass(ClassPool.java:1085)
[testng] at javassist.ClassPool.toClass(ClassPool.java:1028)
[testng] at javassist.ClassPool.toClass(ClassPool.java:986)
[testng] at javassist.CtClass.toClass(CtClass.java:1110)
Try extending from PowerMockTestCase. The TestNG support will also be updated in next version of PowerMock (1.4.9).
I faced this same issue, and struggled a lot. Finally, found the following solution:
Another alternative is to set the object-factory to org.powermock.modules.testng.PowerMockObjectFactory in the TestNG suite.xml. Here is a sample suite file:
<suite name="dgf" verbose="10" object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
<test name="dgf">
<classes>
<class name="com.example.ClientTest"/>
</classes>
</test>
</suite>
Of course, you can also extend your test case from PowerMockTestCase as told by Johan.
Mock all the static methods in static class before proceeding to mock the static method. Try with this:
#Test
public void testMe() {
PowerMock.mockStatic(Static.class);
EasyMock.expect(Static.staticMethod()).andReturn("Mock called").anyTimes();
PowerMock.replay(Static.class,staticClass);
TargetClass tc = new TargetClass();
String output = tc.callHere();
PowerMock.verify(Static.class,staticClass);
System.out.println(output);
}