I have a problem with Mockito.
Is it possible to do such a thing:
ClassX x = mock(ClassX.class)
when(x.methodB()).thenReturn("toto");
String result = x.methodA();
I'm working with Mockito 1.7.
I saw there was a "spy" system but they say it's not recommended to use it (why?) on the item we test...
I tried that spy function anyway but i get a strange behaviour.
Check what i want to do:
Real code:
String methodA(String arg) {
return this.methodB(arg);
}
String methodB(String arg) {
return "toto";
}
Test code:
#Test
public void testTest() {
final ClassX x = spy( new ClassX() );
final String argument = "arg";
doReturn("good").when(helper).methodB(argument);
assertTrue( x.methodB(argument).equals("good") );
assertTrue( x.methodA(argument).equals("good") );
}
As they said i avoided the when thenReturn syntax that could be a problem with a spy (but it doesn't work either anyway)
The strange thing is that:
assertTrue( x.methodB(argument).equals("good") );
is OK
Only the second
assertTrue( x.methodA(argument).equals("good") );
is not OK
Actually helper.methodA(argument) returns "toto" -> the real result and not the mock result
It isn't possible to tell mockito to return "good" in this case??? It seems when the test class call methodB it's ok, but if a method of the spy calls the methodB it doesn't work anymore...
I don't know what to do... is it such a strange thing to unit-test 2 methods of the same class and make the tests independent from each others so that a famous mock-test framework doesn't implement this basic function? Isn't it what we just call real unit-testing? Don't understand why they say to avoid using spy method on the tested object...
Thanks
UPDATE:
I wrote the stuff below, and then moments later discovered .thenCallRealMethod() which allows you to effectively perform partially stubbing. Mockito authors recommend you use refactoring to separate dependencies into different classes; but they do provide the means to partially stub. I have added a test method to demonstrate this approach, and leave my original comments.
ORIGINAL:
I really like Mockito, but this is the one place where EasyMock wins out. I have two solutions for you that don't involve Mockito. The first is to override methodB on your testing instance. The other is to partially mock with EasyMock:
import org.junit.Test;
import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;
public class PartialMockTest {
class ClassX {
String methodA(String arg) {return methodB(arg);}
String methodB(String arg) {return "toto";}
}
#Test
public void MockitoOnClassX(){
ClassX classx = mock(ClassX.class);
when(classx.methodB("hiyas")).thenReturn("tomtom");
when(classx.methodA(anyString())).thenCallRealMethod();
String response = classx.methodA("hiyas");
assertEquals("tomtom",response);
}
#Test
public void OverrideOnClassX() {
ClassX classx = new ClassX(){#Override String methodB(String arg){return "tomtom";}};
String response = classx.methodA("hiyas");
assertEquals("tomtom",response);
}
#Test
public void PartialMockOnClassX() throws NoSuchMethodException {
ClassX classx = createMockBuilder(ClassX.class).addMockedMethod("methodB").createMock();
expect(classx.methodA("hiyas")).andReturn("tomtom");
replay(classx);
String response = classx.methodA("hiyas");
assertEquals("tomtom",response);
}
}
The spy is a different object from the spied object. The spy only delegates to the spied object. So when the spied object calls methodB from methodA, it will call it on itself, not on the spy.
Related
The following line seems to mock all static methods in the class:
MockedStatic <Sample> sampleMock = Mockito.mockStatic( Sample.class );
sampleMock.when( () -> Sample.sampleStaticMethod( Mockito.any( String.class ) ) ).thenReturn( "response" );
Is it possible to mock just one static method in a class?
By default all methods are mocked. However, using Mockito.CALLS_REAL_METHODS you can configure the mock to actually trigger the real methods excluding only one.
For example given the class Sample:
class Sample{
static String method1(String s) {
return s;
}
static String method2(String s) {
return s;
}
}
If we want to mock only method1:
#Test
public void singleStaticMethodTest(){
try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
mocked.when(() -> Sample.method1(anyString())).thenReturn("bar");
assertEquals("bar", Sample.method1("foo")); // mocked
assertEquals("foo", Sample.method2("foo")); // not mocked
}
}
Be aware that the real Sample.method1() will still be called. From Mockito.CALLS_REAL_METHODS docs:
This implementation can be helpful when working with legacy code. When
this implementation is used, unstubbed methods will delegate to the
real implementation. This is a way to create a partial mock object
that calls real methods by default.
...
Note 1: Stubbing partial mocks using
when(mock.getSomething()).thenReturn(fakeValue) syntax will call the
real method. For partial mock it's recommended to use doReturn
syntax.
So if you don't want to trigger the stubbed static method at all, the solution would be to use the syntax doReturn (as the doc suggests) but for static methods is still not supported:
#Test
public void singleStaticMethodTest() {
try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
doReturn("bar").when(mocked).method1(anyString()); // Compilation error!
//...
}
}
About this check this issue.
The following line seems to mock all static methods in the class:
MockedStatic <Sample> sampleMock = Mockito.mockStatic( Sample.class );
sampleMock.when( () -> Sample.sampleStaticMethod( Mockito.any( String.class ) ) ).thenReturn( "response" );
Is it possible to mock just one static method in a class?
By default all methods are mocked. However, using Mockito.CALLS_REAL_METHODS you can configure the mock to actually trigger the real methods excluding only one.
For example given the class Sample:
class Sample{
static String method1(String s) {
return s;
}
static String method2(String s) {
return s;
}
}
If we want to mock only method1:
#Test
public void singleStaticMethodTest(){
try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
mocked.when(() -> Sample.method1(anyString())).thenReturn("bar");
assertEquals("bar", Sample.method1("foo")); // mocked
assertEquals("foo", Sample.method2("foo")); // not mocked
}
}
Be aware that the real Sample.method1() will still be called. From Mockito.CALLS_REAL_METHODS docs:
This implementation can be helpful when working with legacy code. When
this implementation is used, unstubbed methods will delegate to the
real implementation. This is a way to create a partial mock object
that calls real methods by default.
...
Note 1: Stubbing partial mocks using
when(mock.getSomething()).thenReturn(fakeValue) syntax will call the
real method. For partial mock it's recommended to use doReturn
syntax.
So if you don't want to trigger the stubbed static method at all, the solution would be to use the syntax doReturn (as the doc suggests) but for static methods is still not supported:
#Test
public void singleStaticMethodTest() {
try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
doReturn("bar").when(mocked).method1(anyString()); // Compilation error!
//...
}
}
About this check this issue.
I have code similar to this
class Util{
public String transform(String str);
//lots of logic including ajax calls
return("Modified"+str);
}
public caseChange(String str){
//lots of logic including ajax calls
return str.toUpperCase()
}
class TextParser extends Util{
public String parse(str)
//lots of logic to modify str
str = caseChange(str);
//some more logic to modify str
return transform(str);
}
Is there anyway to mock the caseChange and transform methods to return some mocked data and prevent a call to the superclass when i call
String result = new TextParser().parse("hello")
in the unit test class to assert result.
The transform and changeCase are over simplified in my example. In reality they perform ajax calls and there is a ton of other logic. I want to mock them out so that can unit test just this part an then unit test the super methods later
You may need to create another subclass like
class TextParserForTest extends TextParser {
#Override
public String parse(String str) {
super.parse(str);
}
#Override
public String caseChange(String str) {
return "whatever";
}
}
edit : use mockito to this :
import static org.mockito.Mockito.*;
import org.junit.Test;
#Test
public void test() {
TextParser tp = mock(TextParser.class);
// all the methods that you want to test
when(tp.parse(any())).thenCallRealMethod();
when...
// all the methods that you want to mock
when(tp.caseChange(any()).thenReturn("whatever");
when...
}
In your given example: you simply don't do that. Your methods are only working on your inputs; so it should absolutely not matter where those methods are implemented.
In other words: it seems most appropriate for you to focus on contract checking tests only. Like:
#Test
public testWhatever() {
assertThat(new TextParser.parse("hello"), is("expected output"));
}
Yes, you can probably mock such things using Mockito/Powermock; but you shouldn't! You see, your production code is directly calling those methods; so you want to test that calling parse gives you expected results (while using all the code that will also run in a production setup!)
Edit: given your comment about that methods being "complicated". Then I suggest: do not use inheritance here. You should not make class B a subclass of A just to have easy access to some methods. In other words: inheritance is about modeling an IS-A relation. So, a TextParser is a Util? Doesn't sound very convincing.
Thus: you better turn to composition here. Your TextParser should use a Util object. And that one can be provided via dependency injection; and your need to mock with inherited methods vanishes completely!
You can use the spy functionality of Mockito. The spy calls real methods unless they are stubbed.
#Test
public void testParse() {
TextParser textParser = Mockito.spy(new TextParser());
when(textParser.caseChange(Matchers.anyString())).thenReturn("mocked");
Assert.assertEquals("Modifiedmocked", textParser.parse("hello"));
}
I am using mockito as mocking framework. I have a scenerio here, my when(abc.method()).thenReturn(value) does not return value, instead it returns null.
public class DQExecWorkflowServiceImplTest {
#InjectMocks
DQExecWorkflowServiceImpl dqExecWorkflowServiceImpl = new DQExecWorkflowServiceImpl();
#Mock
private DQUtility dqUtility;
#Mock
private DqExec dqExec;
#Mock
private DqCntlDefn dqCntlDefn;
#Mock
private DqCntlWfDefn dqCntlWfDefn;
#Mock
private DqCntlWfDefnTyp dqCntlWfDefnTyp;
#Mock
private IDQControlWfDefTypeService controlWfDefTypeService;
#Before
public void setUp() throws Exception {
dqExec = new DqExec();
dqCntlWfDefn = new DqCntlWfDefn();
dqUtility = new DQUtility();
dqCntlWfDefnTyp = new DqCntlWfDefnTyp();
dqCntlWfDefnTyp.setDqCntlWfDefnTypCd("MIN_INCLUSIVE_VAL");
dqExecWorkflowServiceImpl
.setControlWfDefTypeService(controlWfDefTypeService);
}
#Test
public void testExecuteWorkflow() {
when(controlWfDefTypeService.getDqCntlWfDefnTypCd(dqCntlWfDefn))
.thenReturn(dqCntlWfDefnTyp);
dqExecWorkflowServiceImpl.executeWorkflow(dqExec, dqCntlWfDefn);
}
}
Java class
#Override
public DqCntlWfExec executeWorkflow(final DqExec dqExec,
final DqCntlWfDefn dqCntlWfDefn) {
final DqCntlWfExec dqCntlWfExec = new DqCntlWfExec();
dqCntlWfExec.setDqCntlWfExecEffDt(dqUtil.getDefaultEffectiveDt());
dqCntlWfExec.setDqCntlWfExecExpDt(dqUtil.getDefaultExpiryDt());
dqCntlWfExec.setDqCntlWfDefn(dqCntlWfDefn);
dqCntlWfExec.setDqExec(dqExec);
final DqCntlWfDefnTyp dqCntlWfDefnTyp = controlWfDefTypeService
.getDqCntlWfDefnTypCd(dqCntlWfDefn);
String workflowType = null;
if(null!=dqCntlWfDefnTyp){
workflowType = dqCntlWfDefnTyp.getDqCntlWfDefnTypCd();
}
When ever i run the test file the when is not working and i am using mockito1.8.5 jar in the buildpath. The service call is being mocked but returns the null value.
final DqCntlWfDefnTyp dqCntlWfDefnTyp = controlWfDefTypeService
.getDqCntlWfDefnTypCd(dqCntlWfDefn);
This object dqCntlWfDefnTyp is null
I have done this before and there was no problem with the when, It seems to be working with files i have done before. I had followed the same procedure for the test file but i couldnt figure out the issue. Can anyone please assist me
Thanks to all the folks in advance
Mockito mock works when we mock the objects loosely.
Here is the change i have made to make it work:
when(controlWfDefTypeService.getDqCntlWfDefnTypCd(any(DqCntlWfDefn.class))
.thenReturn(dqCntlWfDefnTyp);
Instead of passing the object of the Mock class, I passed the class with the Matcher any() and it works.
TL;DR If some arguments in your test are null, be sure to mock the parameter call with isNull() instead of any(SomeClass.class).
Explanation
This might not be the answer that helps OP, but might be useful for someone else. In my case the setup was all good, however, some mocks returned the desired thenReturn(...) value and some didn't.
It's important to understand, that the method call you're trying to mock (i.e. the method in when(someMock.methodToMock)) has to match the actual call and not the signature only.
In my case, I mocked a method with a signature:
public void SomeValue method(String string, SomeParam param)
The call however, in the test was something like:
method("some string during test", null);
Now if you mock the call with:
when(MockedClass.method(anyString(), any(SomeParam.class))
Mockito will not match it even though the signature is correct. The problem is that Mockito is looking for a call of method() with the arguments String and SomeParam, whereas the actual call was with a String and null. What you have to do is:
when(MockedClass.method(anyString(), isNull())
Hint
Since there are many isNull() implementations in different frameworks, be sure to use this one org.mockito.ArgumentMatchers.isNull.
I think I have found your issue, but not all the credit goes to me.
Since you are trying to mock 'dqCntlWfDefnTyp' in your test class and the object itself is being instantiated in the class that you are trying to test, you inevitably run into some issues. The primary problem is that the object cannot be mocked because it is being recreated in during the test.
There are a few options, but the best choice in my humble opinion is using PowerMockito. You will be able to replace the object within the class that is being tested with the one you mock.
An excellent example of this usage of PowerMockito from #raspacorp on this question:
public class MyClass {
void method1{
MyObject obj1=new MyObject();
obj1.method1();
}
}
And the test class...
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
#Test
public void testMethod1() {
MyObject myObjectMock = mock(MyObject.class);
when(myObjectMock.method1()).thenReturn(<whatever you want to return>);
PowerMockito.whenNew(MyObject.class).withNoArguments().thenReturn(myObjectMock);
MyClass objectTested = new MyClass();
objectTested.method1();
... // your assertions or verification here
}
}
I had the same problem. The solution for me was to put the Mockito.when(...).thenReturn(...); into the #Before-SetUp method.
Just like Younes EO said: it usually is related to null arguments being passed to mocked functions.
One thing worth adding is that if you're using Kotlin for your tests (and you have mockito-kotlin in your project), for Nullable arguments you should usually use anyOrNull() instead of any().
Relevant to the topic, just in case this helps someone. My mockito.when wasn't working when asserting anyString() reason being the String within the tested class was an injected value from a properties file. The following line set the injected value in the unit test:
ReflectionTestUtils.setField(bean, "theVariable", "theValue");
I haved the same problem when i make test for controler. Use #MockBean instead #Mock
I know you can set several different objects to be be returned on a mock. Ex.
when(someObject.getObject()).thenReturn(object1,object2,object3);
Can you do the same thing with a spied object somehow? I tried the above on a spy with no luck. I read in the docs to use doReturn() on a spy like below
doReturn("foo").when(spy).get(0);
But deReturn() only accepts one parameter. I'd like to return different objects in a specific order on a spy. Is this possible?
I have a class like the following and i'm trying to test it. I want to test myClass, not anotherClass
public class myClass{
//class code that needs several instances of `anotherClass`
public anotherClass getObject(){
return new anotherClass();
}
}
You can chain doReturn() calls before when(), so this works (mockito 1.9.5):
private static class Meh
{
public String meh() { return "meh"; }
}
#Test
public void testMeh()
{
final Meh meh = spy(new Meh());
doReturn("foo").doReturn("bar").doCallRealMethod().when(meh).meh();
assertEquals("foo", meh.meh());
assertEquals("bar", meh.meh());
assertEquals("meh", meh.meh());
}
Also, I didn't know you could do when(x.y()).thenReturn(z1,z2), when I have to do this I use chained .thenReturn() calls as well:
when(x.y()).thenReturn(z1).thenThrow().thenReturn(z2)