How do I test a void method using JUnit and Mockito? - java

My void method changes boolean variable value in the class. How do DI check that?
I have:
mocked class object
called the method with proper parameters
checked the instance variable
But that doesn't change the value of instance variable. How do I do this?
ReferenceLettersBean rf = Mockito.mock(ReferenceLettersBean.class);
rf.setBoolcheck(false);
Mockito.doNothing().when(rf).checkForDuplicates(anyString(), anyString(), anyString());
rf.checkForDuplicates("abcd#emal.com","abd#gmail.com","abcd#gmail.com");
assertEquals(true,rf.getBoolcheck());

DON'T mock the class you are trying to test.
DO mock the classes that interact with the class you are trying to test.
If you want to test that a field in a a class changes from false to true, what you really want to do is something like (I don't have your actual constructor, I'm just guessing):
SomeDependency dependency = mock(SomeDependency.class);
// Make a REAL ReferenceLettersBean
ReferenceLettersBean bean = new ReferenceLettersBean(dependency);
// now make your test
rf.checkForDuplicates("abcd#emal.com","abd#gmail.com","abcd#gmail.com");
assertEquals(true,rf.getBoolcheck());

This boolean value seems to be an internal state. This is not something you can directly test with unit tests unless you make it public or it is detectable by influencing the behavior of another method.

Related

How to JUnit test that my mocked method is called with the parameter i want (not just id, but deep equal matcher)?

Here is a part of my method that i want to test:
protected void myMethod(MyObject o) {
o.setComment("comment");
MyObjectDAO.updateMyObject(o);
}
Here is a part of my JUnit:
#Mock
private MyObjectDAO myObjectDaoMock;
#Test
public void testMyMethod() {
MyObject o = new MyObject();
// Run Test
x.myMethod(o);
// Control
assertEquals("comment", o.getComment());
verify(myObjectDaoMock).updateMyObject(o);
}
The test is green; we are now testing whether the comment attribute of myObject is set, and the update method is called with myObject. But not whether the update method is called with the updated attribute (after setComment method). When we change the position of two lines in myMethod (first updating the object, then setting its attribute), our test is still green.
I thought that the ArgumentCaptor can be useful here. So i made this one:
#Mock
private MyObjectDAO myObjectDaoMock;
#Test
public void testMyMethod() {
MyObject o = new MyObject();
// Run Test
x.myMethod(o);
// Control
ArgumentCaptor<MyObject> argumentCaptor = ArgumentCaptor.forClass(MyObject.class);
verify(myObjectDaoMock).updateMyObject(argumentCaptor.capture());
MyObject oActual = argumentCaptor.getValue();
assertEquals("comment", oActual.getComment());
}
... hoping that the ArgumentCaptor will capture that state of the object, by which the update method is called, so i can be sure that the update method is called with the updated comment attribute. The test is green again. But it still does not test cleverly. When we change the position of two lines in myMethod again (first updating the object, then setting its attribute), our test is still green.
I understand that, the ArgumentCaptor does not create another attribute for himself (argumentCaptor.getValue()), it is the reference of the original object. So since java works with Reference by Value, for JUnit it does not make any difference whether i update the object before or after, as long as the objectIds are same.
How can i actually test that the updateObject method is called with the updated value of myObject?
EDIT: Another idea was (thanks to #Crazyjavahacking) to mock also myObject (although i don't want that), and define a call-order with 2 mocks:
InOrder inOrder = inOrder(o, myObjectDAOMock);
inOrder.verify(o).setComment("comment");
inOrder.verify(myObjectDAOMock).updateMyObject(o);
That still does not test that the method is called with the updated value. It just test the order. When we change our code:
o.setComment("comment");
o.setComment("comment2");
MyObjectDAO.updateMyObject(o);
.. our test would still run green, since the order is correct based on our order definition. But the method is not called with the updated value "comment" as we want.
It is behaving differently because you are mixing 2 concepts:
mocking
assertions
The only way to do what you need is to have mocked both MyObject and MyObjectDAO. In that case you can verify whether the setter was called on MyObject and also the order of calls. In Mockit use the
InOrder inOrder = inOrder(o, myObjectDAOMock);
inOrder.verify(o).setComment("...");
// 1.) inOrder.verify(o, times(0)).setComment(anyString());
inOrder.verify(myObjectDAOMock).updateMyObject(o);
// 2.) assertEquals(o.getComment(), "comment");
// 3.) verifyNoMoreInteractions(o);
construction.
Couple of notes:
this will guaranteed there are no more other invocations to setComment()
if we will use #Spy for MyObject instead of #Mock, we can verify what is the final value of the comment in MyObject instance
this will guarantee no other invocation is performed on the passed instance

EasyMock verify parameter of mocked object

I would like to verify if a parameter of a mocked object is correctly mapped (before the methodcall there is a mapping).
I've created two objects, one of which has the expected values.
I expect the false one to fail, but somehow easymock does not verify if the parameter contains the expected values. How can I fix that?
Real class does:
public SomeObject methodname() {
MyClass parameter = mapper.map(source,Dest.class);
serviceBeingMocked.doSomething(parameter); //<-- want to verify this parameter
}
Test
MyClass correct = ...;
correct.setA=a;
correct.setB=b;
expect(serviceBeingMocked(correct)).andReturn(iDontCare); //this should work
MyClass false = ...;
false.setA=eeeeeeeeeee;
false.setB=ffffffffff;
expect(serviceBeingMocked(false)).andReturn(iDontCare); // this test should fail
Thanks in advance!
Edit: Found the answer (using capture to record the paramter and test the values via assert)
Capture paramter = new Capitre();
expect(serviceBeingMocked(EasyMock.capture(parameter)));
assertEquals(parameter.getValue().getWhatever().equals(correct.getWhatever());
If I understand correctly, this test is a test foe methodname(). And you would like to test that, given a source, the correct MyClass paremeter is created by the mapper, and passed to serviceBeingMocked.doSomething().
So in fact, your unit test for methodname() actually tests the mapper.map() method. That's wrong. You should write a unit test for mapper.map() to test that. Once you've ensured that mapper.map() works as expected, you can test methodname() by mocking the mapper.map() method, and verify that the result of this mocked method is passed to the mocked service (although this test wouldn't add much value).
To be complete, if you really want to go your way and check the value passed to serviceBeingMocked(), then you should use a capture.

Powermock not returning correct object static method

I am using PowerMock to try and mock a final class with static methods, but whenever my code calls MyClass.getInstance() it returns null
In my tests I have annotated the test class
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
In my method to make the mock I do the following
suppressConstructor(MyClass.class);
PowerMock.mockStatic(MyClass.class);
mockClass = PowerMock.createMock(MyClass.class);
expect(MyClass.getInstance()).andReturn(mockClass);
Should PowerMock.createMock create an EasyMock class?
When I call this in my code (MyClass.getInstance()), it always returns null but if I step through the test class the variable mockClass gets instantiated.
It seems like you using the EasyMock way of mocking. Have you replayed the MyClass before calling the getInstance() method, e.g.
PowerMock.replay(MyClass.class);
?
From the PowerMock MockStatic documentation:
Use PowerMock.mockStatic(ClassThatContainsStaticMethod.class) to mock all methods of this class.
Use PowerMock.replay(ClassThatContainsStaticMethod.class) to change the class to replay mode.
Use PowerMock.verify(ClassThatContainsStaticMethod.class) to change the class to verify mode.

Mockito: Trying to spy on method is calling the original method

I'm using Mockito 1.9.0. I want mock the behaviour for a single method of a class in a JUnit test, so I have
final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);
The problem is, in the second line, myClassSpy.method1() is actually getting called, resulting in an exception. The only reason I'm using mocks is so that later, whenever myClassSpy.method1() is called, the real method won't be called and the myResults object will be returned.
MyClass is an interface and myInstance is an implementation of that, if that matters.
What do I need to do to correct this spying behaviour?
Let me quote the official documentation:
Important gotcha on spying real objects!
Sometimes it's impossible to use when(Object) for stubbing spies. Example:
List list = new LinkedList();
List spy = spy(list);
// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
In your case it goes something like:
doReturn(resultsIWant).when(myClassSpy).method1();
In my case, using Mockito 2.0, I had to change all the any() parameters to nullable() in order to stub the real call.
My case was different from the accepted answer. I was trying to mock a package-private method for an instance that did not live in that package
package common;
public class AnimalĀ {
void packageProtected();
}
package instances;
class Dog extends Animal { }
and the test classes
package common;
public abstract class AnimalTest<T extends Animal> {
#Before
setup(){
doNothing().when(getInstance()).packageProtected();
}
abstract T getInstance();
}
package instances;
class DogTest extends AnimalTest<Dog> {
Dog getInstance(){
return spy(new Dog());
}
#Test
public void myTest(){}
}
The compilation is correct, but when it tries to setup the test, it invokes the real method instead.
Declaring the method protected or public fixes the issue, tho it's not a clean solution.
The answer by Tomasz Nurkiewicz appears not to tell the whole story!
NB Mockito version: 1.10.19.
I am very much a Mockito newb, so can't explain the following behaviour: if there's an expert out there who can improve this answer, please feel free.
The method in question here, getContentStringValue, is NOT final and NOT static.
This line does call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
This line does not call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
For reasons which I can't answer, using isA() causes the intended (?) "do not call method" behaviour of doReturn to fail.
Let's look at the method signatures involved here: they are both static methods of Matchers. Both are said by the Javadoc to return null, which is a little difficult to get your head around in itself. Presumably the Class object passed as the parameter is examined but the result either never calculated or discarded. Given that null can stand for any class and that you are hoping for the mocked method not to be called, couldn't the signatures of isA( ... ) and any( ... ) just return null rather than a generic parameter* <T>?
Anyway:
public static <T> T isA(java.lang.Class<T> clazz)
public static <T> T any(java.lang.Class<T> clazz)
The API documentation does not give any clue about this. It also seems to say the need for such "do not call method" behaviour is "very rare". Personally I use this technique all the time: typically I find that mocking involves a few lines which "set the scene" ... followed by calling a method which then "plays out" the scene in the mock context which you have staged... and while you are setting up the scenery and the props the last thing you want is for the actors to enter stage left and start acting their hearts out...
But this is way beyond my pay grade... I invite explanations from any passing Mockito high priests...
* is "generic parameter" the right term?
One more possible scenario which may causing issues with spies is when you're testing spring beans (with spring test framework) or some other framework that is proxing your objects during test.
Example
#Autowired
private MonitoringDocumentsRepository repository
void test(){
repository = Mockito.spy(repository)
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
In above code both Spring and Mockito will try to proxy your MonitoringDocumentsRepository object, but Spring will be first, which will cause real call of findMonitoringDocuments method. If we debug our code just after putting a spy on repository object it will look like this inside debugger:
repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$
#SpyBean to the rescue
If instead #Autowired annotation we use #SpyBean annotation, we will solve above problem, the SpyBean annotation will also inject repository object but it will be firstly proxied by Mockito and will look like this inside debugger
repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$
and here is the code:
#SpyBean
private MonitoringDocumentsRepository repository
void test(){
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
Important gotcha on spying real objects
When stubbing a method using spies , please use doReturn() family of methods.
when(Object) would result in calling the actual method that can throw exceptions.
List spy = spy(new LinkedList());
//Incorrect , spy.get() will throw IndexOutOfBoundsException
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
I've found yet another reason for spy to call the original method.
Someone had the idea to mock a final class, and found about MockMaker:
As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line: mock-maker-inline
Source: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods
After I merged and brought that file to my machine, my tests failed.
I just had to remove the line (or the file), and spy() worked.
One way to make sure a method from a class is not called is to override the method with a dummy.
WebFormCreatorActivity activity = spy(new WebFormCreatorActivity(clientFactory) {//spy(new WebFormCreatorActivity(clientFactory));
#Override
public void select(TreeItem i) {
log.debug("SELECT");
};
});
As mentioned in some of the comments, my method was "static" (though being called on by an instance of the class)
public class A {
static void myMethod() {...}
}
A instance = spy(new A());
verify(instance).myMethod(); // still calls the original method because it's static
Work around was make an instance method or upgrade Mockito to a newer version with some config: https://stackoverflow.com/a/62860455/32453
Bit late to the party but above solutions did not work for me , so sharing my 0.02$
Mokcito version: 1.10.19
MyClass.java
private int handleAction(List<String> argList, String action)
Test.java
MyClass spy = PowerMockito.spy(new MyClass());
Following did NOT work for me (actual method was being called):
1.
doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());
2.
doReturn(0).when(spy , "handleAction", any(), anyString());
3.
doReturn(0).when(spy , "handleAction", null, null);
Following WORKED:
doReturn(0).when(spy , "handleAction", any(List.class), anyString());

How to inject EasyMock mock into tested class private field

I'm using EasyMock to create mock that is one of private parameters (without setter) in tested class. I tried using reflection - but it does not work correctly.
public class TestedClassTest{
#Test
public void test(){
TestedClass instance = new TestedClass();
MockedClass mocked = EasyMock.createMock(MockedClass.class);
Data data = new Data();
//Void setter
DataType dataType = (myDataType.DataType) EasyMock.anyObject();
mocked.setDataType(dataType);
EasyMock.expectLastCall();
//expect
EasyMock.expect(mocked.getData()).andReturn(data);
EasyMock.replay(mocked);
Field field = instance.getClass().getDeclaredField("mockedClass")
field.setAccessible(true);
field.set(instance, mocked);
//run tested method
instance.someAction();
EasyMock.verify(mocked);
}
}
Im getting FAILED info:
Unexpected method call MockedClass.setDataType(myData.MyData#104306d75):
MockedClass.getData(): expected: 1, actual: 0
junit.framework.AssertionFailedError:
Unexpected method call MockedClass.setDataType(myData.MyData#132006d75):
MockedClass.getData(): expected: 1, actual: 0
Im sure this method is fired on "MockedClass" object during tested "instance.someAction()"
How to resolve this problem?
Edited - Answer :
After correcting doubled replay.mocked() I found (so simple!) that one more void method should be declared using EasyMock.expectLastCall()
Your reflection code looks fine.
It's been a long time since I've used EasyMock, but isn't replay only supposed to be called once per mock in a test? You are calling it twice. Try getting rid of the first replay call.
In this case, does it make sense to have the field that contains the mock be public? In general, collaborators should be set via either constructor or setter, eliminating the need for reflection at all.
EDIT -- based on your updates -- the error indicates setDataType was called on the mock, but the mock did not expect it to be called. Perhaps your class is calling it twice, perhaps it is being called out of order, or calling it with an argument you didn't expect (although I would expect the error to be different in this case).

Categories

Resources