Is there any way to get the parameter annotations of a method in child class? I tried using the getParameterAnnotations but it not works. I wrote a test class to demonstrate:
public class ParameterAnnotationInheritanceTest {
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
#Inherited
public #interface MockAnnotation {
}
public class A {
public void test(#MockAnnotation String value) {
}
}
public class B extends A {
#Override
public void test(String value) {
}
}
#Test
public void TestA() throws NoSuchMethodException, SecurityException {
Method AMethod = A.class.getMethod("test", String.class);
Annotation[][] AMethodParameterAnnotations = AMethod.getParameterAnnotations();
assertTrue(Arrays.asList(AMethodParameterAnnotations[0]).size() > 0);
}
#Test
public void TestB() throws NoSuchMethodException, SecurityException {
Method BMethod = B.class.getMethod("test", String.class);
Annotation[][] BMethodParameterAnnotations = BMethod.getParameterAnnotations();
assertTrue(Arrays.asList(BMethodParameterAnnotations[0]).size() > 0);
}
}
Thanks in advance!
It does not work because the test method in the child class B is not the same test method as in the super class. By overriding it, you have practically defined a new test method that gets called instead of the original one. If you define your child class like this
public class B extends A {
}
and run your code again, it works fine because it is the inherited test method that gets called, which is what you want as far as I understand.
Related
I need to inject a mock object into a method where a new MyClass object is instantiated.
private MyClass<?> c;
public void myMethod(final String s) {
c = new MyClass<>(s);
c.callToMock();
}
And the class I'm mocking has a constructor with a generic parameter.
public class MyClass<T> {
public MyClass(final T t) {
// do whatever
}
}
Now, in my test, I've created a mock for the class.
When new is called, it should inject that mock.
#RunWith (PowerMockRunner.class)
public class TestClass {
#SuppressWarnings ("unchecked")
public void myMethodTest() throws Exception {
MyClass<String> myMock = (MyClass<String>) EasyMock.createMock(MyClass.class);
PowerMock.expectNew(MyClass.class, "my argument")
.andReturn(myMock);
myMock.callToMock();
EasyMock.expectLastCall().once();
EasyMock.replay(myMock);
PowerMock.replayAll();
...
}
When I run the test, it doesn't catch the new call and just instantiates an actual MyClass object.
I don't know if it's not able to match the constructor or what.
Any help would be appreciated, thanks.
You need to add a #PrepareForTest(MyTestedClass.class) on your test class to prepare the tested class to mock the new.
Here is a fully working test:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyTestedClass.class)
public class TestClass {
#Test
#SuppressWarnings("unchecked")
public void myMethodTest() throws Exception {
MyClass<String> myMock = (MyClass<String>) EasyMock.createMock(MyClass.class);
myMock.callToMock();
PowerMock.expectNew(MyClass.class, "my argument")
.andReturn(myMock);
EasyMock.replay(myMock);
PowerMock.replayAll();
MyTestedClass tested = new MyTestedClass();
tested.myMethod("my argument");
}
}
I am trying to test a method whom depending on some conditions will execute its code or its super class's one.
Here is the code of the class and its parent:
public class ParentClass {
public Object doStuff(Parameters parameters) {
// do some business stuff
return parentResult;
}
}
The inherited class's one:
public class InheritedClass extends ParentClass {
#Override
public Object doStuff(Parameters parameters) {
if (parameters.getCondition()) {
return super.doStuff(parameters);
}
//do some business stuff
return inheritedResult;
}
}
So, when trying to test the case when the parameters.getCondition() is true, I have to mock the call on the super method and verify it.
But when I do this (mocking the call for the super.doStuff()), I also mock the call to the InhertitedClass.doStuff().
Here's the solution I tried:
#RunWith(MockitoJUnitRunner.class)
public class InheritedClassTest {
#Mock
private Parameters parameters;
#Spy
private InheritedClass inherited = new InheritedClass();
#Test
public void testDoStuff(Object parameters) throws Exception {
given(parameters.getCondition()).willReturn(true);
doCallRealMethod().doReturn(value).when(inherited).doStuff(parameters);
Mockito.verify(inherited, times(2)).doStuff(parameters);
}
}
I also tried this stubbing:
when(inherited.doStuff(parameters)).thenCallRealMethod().thenReturn(value);
and this one:
given(((ParentClass)inherited).doStuff(parameters)).willReturn(value);
In all this cases, the code of the parent class was really executed.
So, I was wondering if there is any efficient way to mock the call of the super class method using mockito?
You can use Mockito's spy(), which you already tried to do. But I think a different way of using spy() will make it work.
ParentClass.java
public class ParentClass {
public String doStuff(final String parameters) {
return "parent";
}
}
InheritedClass.java
public class InheritedClass extends ParentClass {
#Override
public String doStuff(final String parameters) {
if (parameters.equals("do parent")) {
return super.doStuff(parameters);
}
return "child";
}
}
InheritedClassTest.java
public class InheritedClassTest {
#Test
public void testDoStuff() throws Exception {
final InheritedClass inheritedClass = Mockito.spy(new InheritedClass());
Mockito.doReturn("mocked parent").when((ParentClass)inheritedClass).doStuff(Mockito.eq("do parent"));
final String result = inheritedClass.doStuff("do parent");
assertEquals("mocked parent", result);
assertNotEquals("parent", result);
final String resultChild = inheritedClass.doStuff("aaa");
assertEquals("child", resultChild);
}
}
However, I do not think using spy() is a good practice. I would personally refactor your code.
I have try following code:
package ro.ex;
/**
* Created by roroco on 11/11/14.
*/
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.mockito.Mockito.*;
public class ExTest extends junit.framework.TestCase {
class C {
public String m() {
return null;
}
}
public void testM() throws Exception {
when(new C().m()).thenAnswer(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
return (String) args[0];
}
});
}
}
i hope i can change a real instance meth not a mock, but above code raise:
when() requires an argument which has to be 'a method call on a mock'.
my question is: how to fix it.
I assume this is a sample code you created to ask a question here but in real, C should be the class under test (not a class within your test).
Class MyClassToTest {
public String m() {...}
}
Now in your test, mock class C. #Mock C c and followed by when(c.m()).thenAnswer..... in the test method.
Not sure why you would need that, but you can use spy:
public void testM() throws Exception {
C c = Mockito.spy(new C());
// actual method
c.m();
// stubbed method
when(c.m()).thenAnswer(...);
}
Alternatively, you can mock the object, and call thenCallRealMethod() when needed.
How can we identify whether a particular method belongs to an abstract class or an interface? Is there any way to identify it or not?
The only valid answer on this question should be:
You do not want to know that. If you need to know that, there is something wrong with your classes design.
But nevertheless you can do it via reflection for interfaces at least.
Be careful with your first try, because this will return false, even if it is declared in an interface of the class. (See example below)
TestImpl.class.getMethod("test").getDeclaringClass().isInterface(); // false
You will need to do more reflection magic to get the correct result like this:
public class ReflectionTest {
interface Test {
void test();
}
class TestImpl implements Test {
#Override
public void test() {
}
}
private static boolean isInterfaceMethod(Class clazz, String methodName) throws NoSuchMethodException, SecurityException {
for (Class interfaze : clazz.getMethod(methodName).getDeclaringClass().getInterfaces()) {
for (Method method : interfaze.getMethods()) {
if (method.getName().equals(methodName)) {
return true;
}
}
}
return false;
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
System.out.println(isInterfaceMethod(TestImpl.class, "test")); // true
}
}
I have one Java class that uses annotations. I want to write a version that extends it and changes the annotations on existing methods.
So there will be a method that has:
#myAnnotation(value=VALUE_THAT_CHANGE_IN_SUBCLASS)
myMethod(){
}
The subclass will have a couple new methods, but will mostly just change annotations in the manner I said.
Though I'm not sure why you'd want to, you'd need to extend the class, override the methods, and apply the annotations:
public class App
{
public static void main(String[] args) throws NoSuchMethodException
{
Class<MyClass> c = MyClass.class;
MyAnnotation a = c.getMethod("someMethod",null).getAnnotation(MyAnnotation.class);
System.out.println(a.name());
Class<MySubclass> c2 = MySubclass.class;
a = c2.getMethod("someMethod",null).getAnnotation(MyAnnotation.class);
System.out.println(a.name());
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface MyAnnotation {
String name() default "";
}
class MyClass {
#MyAnnotation(name="Some value")
public String someMethod() {
return "Hi!";
}
}
class MySubclass extends MyClass {
#Override
#MyAnnotation(name="Some other value")
public String someMethod() {
return super.someMethod();
}
}
Output:
Some value
Some other value