How to use expectNew for constructor with generic parameter? - java

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");
}
}

Related

Mockito: Override mock values in different methods

#RunWith(MockitoJUnitRunner.class)
public class Test {
#Mock
private SomeDependency<T> obj;
#InjectMocks
private SomeClass mainObj;
#Test
public void dependencyShouldBeNotNull() {
//here I need one value of SomeDependency obj
assertEquals(2, mainObj.method())
}
#Test
public void dependencyShouldBeNull() {
//here I need SomeDependency obj to be null
assertEquals(1, mainObj.method())
}
Main class:
class SomeClass {
private SomeDependency<T> field;
public int method() {
if(field==null)
return 1;
else
return 2;
}
}
And my question: how to override value of mock according to different methods needs?
Edited
In main SomeClass I have code like this:
if (obj != null) {
//perform some actions
}
The easiest way to do it is with 2 test classes instead of one because when it executes your test methods it is already too late since the mock has already been injected (unless you use refection which should be avoided).
The first test
#RunWith(MockitoJUnitRunner.class)
public class Test1 {
#Mock
private SomeDependency<T> obj;
#InjectMocks
private SomeClass mainObj;
#Test
public void dependencyShouldBeNotNull() {
//here I need one value of SomeDependency obj
assertEquals(2, mainObj.method());
}
}
The second test
#RunWith(MockitoJUnitRunner.class)
public class Test2 {
#InjectMocks
private SomeClass mainObj;
#Test
public void dependencyShouldBeNull() {
//here I need SomeDependency obj to be null
assertEquals(1, mainObj.method());
}
}
If you want to do it with only one test class, it is still possible but it is more like a hack because you want a conditional injection which is not a conventional approach, so you will need to inject the mocks programmatically with MockitoAnnotations.initMocks(obj).
Instead of injecting the mocks directly into the test class, we need to rely on wrapper classes that will contain or not the field obj, if not present nothing will be injected so it will be null otherwise you will have a mock injected.
public class TestInjectMocks {
/**
* Small interface that will be implemented by the wrapper classes
* only used to get the main class
*/
public interface TestConfig {
SomeClass getSomeClass();
}
#Test
public void dependencyShouldBeNotNull() {
// This class will allow to get an instance of SomeClass
// with the field injected
TestConfig obj = new TestConfig() {
#Mock
private SomeDependency<T> obj;
#InjectMocks
private SomeClass mainObj;
#Override
public SomeClass getSomeClass() {
return mainObj;
}
};
MockitoAnnotations.initMocks(obj);
SomeClass mainObj = obj.getSomeClass();
//here I need one value of SomeDependency obj
assertEquals(2, mainObj.method());
}
#Test
public void dependencyShouldBeNull() {
// This class will allow to get an instance of SomeClass
// without the field injected
TestConfig obj = new TestConfig(){
#InjectMocks
private SomeClass mainObj;
#Override
public SomeClass getSomeClass() {
return mainObj;
}
};
MockitoAnnotations.initMocks(obj);
SomeClass mainObj = obj.getSomeClass();
//here I need SomeDependency obj to be null
assertEquals(1, mainObj.method());
}
}
NB: As we call MockitoAnnotations.initMocks(obj) explicitly the annotation #RunWith(MockitoJUnitRunner.class) is not needed anymore.
Based on what you've posted, I recommend using the 'Mockito.when()' method for the first method, then setting obj = null; as #Seelenvirtuose suggests. If that doesn't work, you might want to pass in a different Mocked out object which is initialized to null. See this example.

How to mock a call of an inner method from a Junit

I have MyClass and I am doing a test-class for every method (Method1Test)
public class MyClass {
public int method1(){
int a = method2();
return a;
}
public int method2(){
return 0;
}
}
#RunWith(MockitoJUnitRunner.class)
public class Method1Test {
#InjectMocks
private MyClass myClass = new MyClass();
#Before
public void setup(){}
#Test
public void test01(){
Mockito.when(myClass.method2()).thenReturn(25);
int a = myClass.method1();
assertTrue("We did it!!!",a==25);
}
}
The problem is that I am not able to mock the call to method2 to make it return a diferent value. The Mockito sentence don't do the work.
Very thanks ^_^
You have to create a spy on the class-under-test and partially mock it by redefining the behavior for the method2() of the spy
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
public class Method1Test {
private MyClass myClass = new MyClass();
#Test
public void test01(){
//given
MyClass spy = spy(myClass); //create a spy for class-under-test
when(spy.method2()).thenReturn(25); //partially override behavior of the spy
//when
int a = spy.method1(); //make the call to method1 of the _spy_!
//then
assertEquals(25, a);
}
}
Apart from this, you don't require neither the Mockito Runner nor the #InjectMocks for your test as you're doing no injection of #Mock annotated mocks into the class-under-test.
Further, the message in the assertTrue statement is only displayed, when the condition of the assertion is NOT fulfilled. So it should be at least "We failed!!!" ;)
In the end I find a transversal solution without create a new class (I haven't been able to do it because it is forbbiden in the actual project). I have overwrited the method in the test.
The solution is
public class MyClass {
public int method1(){
int a=0;
a=method2();
return a;
}
public int method2(){
return 1;
}
}
#RunWith(MockitoJUnitRunner.class)
public class Method1Test {
#InjectMocks
private MyClass myClass = new MyClass(){
public int method2(){
return 25;
}
};
#Before
public void setup(){}
#Test
public void test001(){
Mockito.when(myClass.method2()).thenReturn(25);
int a = myClass.method1();
assertTrue("We did it!!!",a==25);
}
}
I tried the solution using the code below, but It didn't pass.
Mockito.when(myClass.method2()).thenReturn(25);
Afterwards, Instead of the code snippet above, I tried something different and the test passed successfully. Take a look:
Mockito.doReturn(25).when(myClass).method2();
In order to mock a test (It might be a inner method), you have to use doReturn() method.
You can use doThrow(), doAnswer(), doNothing(), doReturn() and doCallRealMethod() in place of the corresponding call with when(), for any method. It is necessary when you
stub void methods
stub methods on spy objects (see below)
stub the same method more than once, to change the behaviour of a mock in the middle of a test.
but you may prefer to use these methods in place of the alternative
with when(), for all of your stubbing calls.
Furthermore information can be read here https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#12
Instead of using mock(class) here we need to use Mockito.spy() to mock the same class we are testing. Then we can mock the method we want as follows.
#Test
public void method1Test() {
MyClass myClass = new MyClass();
MyClass myClass1 = Mockito.spy(myClass);
Mockito.doReturn(1).when(myClass1).method2();
Assert.assertEquals(1, myClass1.method1());
}
}

Stubbing the call of a super class method using Mockito(V 1.9.5)

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.

Mockito: how to use when(instance.meth).thenAnswer without mock

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.

Method Parameter Annotations in overridden methods

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.

Categories

Resources