I here have a simplified version of my problem. Class A has a protected method. Class B inherits this method.
public class A{
protected String getString(){
//some Code
}
}
public class B extends A{
public void doSomething(){
//someCode
String result = getString();
}
}
I now write a Unit-Test with Mockito, which is in another package-test and I want to test the doSomething() method. To do that, I need to mock the getString()-call. Since the method is protected and my test-class is in a differnet package, I can't use doReturn(...).when(classUnderTest).getString(). The thing is, that I spy on class B. So I can't use mock(new B(), Mockito.CALLS_REAL_METHODS).
I tried getting the protected method via Reflection:
Method getString = classUnderTest.getClass().getDeclaredMethod("getString");
getString.setAccessible(true);
But I then don't know how to use this inside doReturn().
You can use 'override and subclass'
B b = new B() {
#Override
protected String getString() {
return "FAKE VALUE FOR TESTING PURPOSES";
};
};
There might be a cleaner way of doing this, but here goes...
Create a mock for "A"
Create another class that extends B and overrides the method
Make the overridden method call the mock
For example...
private A partialMock;
private B classUnderTest;
#Before
public void setup() {
partialMock = mock(A.class);
classUnderTest = new B() {
#Override
protected String getString() {
return partialMock.getString();
}
};
}
#Test
public void shouldDoSomething() {
when(partialMock.toString()).thenReturn("[THE MOCKED RESPONSE]");
classUnderTest.doSomething();
// ...verify stuff...
}
Obviously you don't even need to use mocking, you can just return something directly from the overridden method.
Something like following worked for me, using doReturn() and Junit5's ReflectionSupport.
[Note: I tested on Mockito 3.12.4]
var a = spy(new A);
ReflectionSupport.invokeMethod(
a.getClass().getSuperclass().getDeclaredMethod("getString"),
doReturn("FAKE VALUE FOR TESTING PURPOSES").when(a));
Related
Am trying to mock one static void method, I tried PowerMock but always getting NullPointer exception.
We are trying to mock the below call -
public Class XYZ{
public void method1(){
....
SampleClass.methodTypeStatic1().methodTypeStatic2("xyz", "mno", classVeriable);
}
And the main class is -
public class SampleClass implements SampleClassParent{
private static SampleClass var1;
public static SampleClass methodTypeStatic1(){
if (var1 == null) {
//Do something on var1
}
return var1;
}
public void methodTypeStatic2(String localVar1, String localVar2, DifferentStaticClass localVar3) {
//Do something
}}
Am trying to mock the call like this way in my test class -
#RunWith(PowerMockRunner.class)
#PrepareForTest({SampleClass.class})
public class XYZTest{
#InjectMocks
XYZ xyzTestService;
#Test
public void testMethod1(){
...
PowerMockito.mockStatic(SampleClass.class);
PowerMockito.doNothing().when(SampleClass.methodTypeStatic1());
xyzTestService.method1();
}
Also to be mentioned SampleClass.class is not a part of our code, we have imported this external class into our code base to perform some task.
If you want to mock a non-void method, you need to define the behaviour for this method on the mock. You get the doNothing for free (as this is what mocking does),
however you need to define what the method is supposed to return.
Your test could look like this:
#Test
public void testMethod1() {
SampleClass sample = new SampleClass();
PowerMockito.mockStatic(SampleClass.class);
PowerMockito.when(SampleClass.methodTypeStatic1()).thenReturn(sample);
XYZ xyzTestService = new XYZ();
xyzTestService.method1();
}
You didn't not mention any #Mock annotations, so using #InjectMocks does nothing for you besides creating the XYZ object.
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());
}
}
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 encapsulated the object creation into new method as specified in https://code.google.com/p/mockito/wiki/MockingObjectCreation [Pattern 1: using one-line methods for object creation]
I have used private before makeFoo method. Which is making my work harder.
Wasn't private necessary for makeFoo method?
If so how people handled it?
If you make the method protected you can override it in a test double of your SUT. This way you can make the method return some mock, spy or other type of test double.
If at all possible, however, I'd recommend you to inject the dependency class in the constructor. It saves you some headache and boiler plate code. There are cases where a protected factory method is a "better" solution though, just something to keep in mind.
EDIT: Example of constructor injection:
Going from this
public class MyClass
{
private SomeDependency someDependency;
public MyClass()
{
this.someDependency = new SomeDependency(new A(), new B());
}
public void doWork()
{
_someDependency.doSomething();
}
}
To this
public class MyClass
{
private SomeDependency someDependency;
public MyClass(SomeDependency someDependency)
{
this.someDependency = someDependency;
}
public void doWork()
{
this.someDependency.doSomething();
}
}
This allows you to inject your class with a test double directly rather than inheriting it and overriding some factory method.
I have a class which I need to test.
public class Mockz extends AnotherClass{
final MyOtherClass = getMyOtherClass(); // method in AnotherClass
Integer num = 10;
protected void method1(){
System.out.println("in method 1");
}
protected void method2(){
System.out.println("in method 1");
}
}
And in my test class I have a method like ,
#Test
public testMethod1(){
final Mockz mockz = Mockito.spy(new Mockz()); // line 1
Mockito.when(mockz.method1()).thenReturn("Mocking method 1");
System.out.println(mockz.method1());
}
I think I need to mock the getMyOtherClass() method in the super class, Since when executing line 1 that method gets called.
how can I do that ? Or what is the best way to do this ?
This is purely a problem of class structure: You shouldn't need to (or want to) mock a superclass. When testing, you should test the entirety of your subclass (Mockz), even the parts that apply to the superclass (AnotherClass); otherwise, how would you know that the subclass is fulfilling the entirety of the superclass's contract?
If you're looking to refactor, you may consider switching to a composition/delegate pattern:
public class Mockz implements AnotherInterface {
private final AnotherClass delegate;
public Mockz() { this(new AnotherClass()); }
/** for testing */
Mockz(AnotherClass delegate) { this.delegate = delegate; }
// ...
}
...or consider testing a subclass of your subclass:
#Test
public testMethod1(){
final Mockz mockz = Mockito.spy(new Mockz() {
#Override public OtherClass getMyOtherClass() {}
});
Mockito.when(mockz.method1()).thenReturn("Mocking method 1");
System.out.println(mockz.method1());
}
...but that second one implies that getMyOtherClass is dangerous enough to warrant mocking, which probably means it shouldn't be a part of your object's constructor code path anyway, leading to the third answer: Don't call a "heavy-lifting" method on your initialization path:
public class Mockz extends AnotherClass{
MyOtherClass myOtherClass;
/** Part of construction, but expensive enough to call explicitly. */
void initializeMyOtherClass() {
myOtherClass = getMyOtherClass();
}
}