EasyMock verify parameter of mocked object - java

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.

Related

PowerMockito how to capture a parameter passed to a mock object?

I'm trying to capture a parameter passed in input to a mock object with PowerMockito, this is the code:
//I create a mock object
ClassMocked mock = PowerMockito.mock(ClassMocked.class);
//Create the captor that will capture the String passed in input to the mock object
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
//When the method put is executed on my mock I want the second parameter (that is a String) to be captured
Mockito.verify(mock).put(anyString(), inputDataMapCaptor.capture());
//Creates the instance of the class that I want to test passing the mock as parameter
ClassToTest instance = new ClassToTest(mock);
//Executes the method that I want to test
instance.methodToTest();
/* I know that during the execution of "methodToTest()" mock.put(String,String) will be executed and I want to get the second string parameter. */
When I execute the test I have an exception executing the line Mockito.verify(mock).put(...);
"Wanted but not invoked mock.put(any,Capturing argument);"
What is wrong?
You should call instance.methodToTest(); before Mockito.verify(mock).put(anyString(), inputDataMapCaptor.capture());
verify() verifies that the specified method call did take place.
You can't verify "upfront" that a method call is supposed to happen.
Thus: verify() needs to happen after the facts, not before!

How to test private field is set to supplied value using public method in JUnit?

I have a class:
public class MyEncryptor {
private StringEncryptor stringEncryptor; // this is an interface ref
public void setStringEncryptor(StringEncryptor stringEncryptorImpl) {
if(condition){
this.stringEncryptor = stringEncryptorImpl;
}
}
}
When Testing in JUnit for method setStringEncryptor, i want to test if instance value stringEncryptor is set to what i've supplied in parameter as implementation? or i'm going the wrong way for testing this method?
Below is my failed attempt in a junit test method:
MyEncryptor decryptor = new MyEncryptor ();
StringEncryptor spbe = new StandardPBEStringEncryptor();
decryptor.setStringEncryptor(spbe);
Field f = MyEncryptor .class.getDeclaredField("stringEncryptor");
f.setAccessible(true);
Assert.assertSame(f, spbe);
I want to test that stringEnctyptor is set to spbe in junit
Here you assert that the java.lang.reflect.Field stringEncryptor is the same object than the StringEncryptor object you create for your test :
StringEncryptor spbe = new StandardPBEStringEncryptor();
...
Field f = MyEncryptor .class.getDeclaredField("stringEncryptor");
f.setAccessible(true);
Assert.assertSame(f, spbe);
These are two distinct objects of two distinct and no related classes.
You should first retrieve the value associated to the field :
Object value = f.get(spbe);
and then compare the objects :
Assert.assertSame(value, spbe);
But anyway I don't think it is the good way.
To test a code, the implementation should be testable.
Doing reflection to test the code should be done only if we have really not the choice.
A natural way to test your code is providing a method to get the actual StringEncryptor field.
public StringEncryptor getStringEncryptor(){
return stringEncryptor;
}
In this way you could assert the field value in a straight way.
The unit test you have given, fails because you attempt to compare a Field instance and a StandardPBEStringEncryptor instance using assertSame. What you should do is: assertSame(f.get(decryptor), StandardPBEStringEncryptor)
Notice that we use the Field::get method to retrieve the field's value and the argument we give is the instance whose field value we want to retrieve.
However, regardless of that, unit testing a setter type method is redundant and simply adds extra testing code and testing time for no reason.
i want to test if instance value stringEncryptor is set to what i've
supplied in parameter as implementation? or i'm going the wrong way
for testing this method?
I think you're going the wrong way. Wherever possible I would test that the unit under test does the encryption as expected, not specifically if a private field is being set. You really want to test the unit functionality, and not the details of its implementation.

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

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.

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

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