Mockito: Override mock values in different methods - java

#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.

Related

How to mock enum singleton with jmockit?

I have a dependency on an enum singleton class like
public enum SingletonObject {
INSTANCE;
SingletonObject() {
// some annoying initialization
}
public callDB() {
this.num = num;
}
}
I am trying to test a class like
public class MyClass {
public void doSomething() {
// some code
SingletonObject.INSTANCE.callDB();
}
}
Following this answer, I've tried simply testing the mock with the following code, but I seem to be running into problems with the enum calling its constructor
public class MyClassTest {
#Mocked
private SingletonObject singleton;
#Before
public void setup() {
Deencapsulation.setField(SingletonObject.class, "INSTANCE", singleton);
}
#Test
public void test() {
assertSame(singleton, SingletonObject.INSTANCE);
}
}
Using an interface seems somewhat promising, but I question whether that is the best way of going about this problem.
It looks like PowerMockito is promising as well, but I would like to save that as a last resort for various reasons.
So how can I mock this enum singleton without invoking its constructor?
Try something like this. This creates a partial-mock of 'MyClass' and a Mock SingletonObject, calls the (real) doSomething method of MyClass, and confirms that the (mock) callDB() method of SingletonObject is invoked by it precisely once.
#Test
public void testdoSomething(
#Mocked final SingletonObject singleton)
{
final MyClass clz = new MyClass();
new Expectations(clz)
{
{
SingletonObject.INSTANCE.callDB();
times = 1;
}
};
clz.doSomething();
}

How to use expectNew for constructor with generic parameter?

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

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.

mock of autowired field is null in unit test

Does anyone know why in this example, when running "ATest", I get a null on the line "return b.getBAutoWiredObject().getString();"
Any insight on this would be appreciated.
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#Mock
private A a;
#Test
public void testMethod() {
String testedString = a.method();
assertEquals("blah", testedString);
}
}
#Service("A")
public class A {
public String method() {
B b = new B();
return b.getBAutoWiredObject().getString();
}
}
#Component
public class B {
#Autowired
#Qualifier("Bautowire")
private BAutoWiredObject bAutoWiredObject;
public BAutoWiredObject getBAutoWiredObject() {
return bAutoWiredObject;
}
}
#Service("Bautowire")
public class BAutoWiredObject {
private String string = new String("blah");
public void getString() {
return string;
}
}
Typically, the answer would be it's null because you created the B instance yourself. Spring is not involved in the least, so it hasn't autowired anything.
In this case, your A object is a #Mock and mocks are typically implemented to return null in any method that has a return type that is a reference type. Your method() implementation isn't actually getting called. The mock's implementation is.
This is all assuming your test would actually compile and was valid with a #Test annotated method.
assertEquals(testedString, "blah");
should be
assertEquals("blah", testedString);
The first argument should be the expected value and the second should be the actual value.

Categories

Resources