capturing previous values to verify mock object - java

In mockito, is it possible to capture the previous value set to a field of an object passed to a mock object's method for example the method under test performs this
public void methodUnderTest(){
Person person = new Person();
person.setAge(5);
someObject.setPerson(person);
...
person.setAge(6);
someObject.setPerson(person);
}
What I wanted to know is if I mock someObject, will I be able to verify that someObject performed setPerson to a single object "person" twice but the object had different value for age when setPerson occurred? I tried using ArgumentCaptor but since I passed the same object, I was just able to get the last age.
ArgumentCaptor<Integer> arg = ArgumentCaptor.forClass(Integer.class);
verify(mockObject).setPerson(arg.capture());
List<Integer> captureList = arg.getAllValues();
captureList.get(0).getAge(); // returns 6
captureList.get(1).getAge(); // returns 6
I also tried doing
InOrder in = inOrder(mockObject);
in.verify(mockObject).setPerson(arg.capture());
assertEquals(5, arg.getValue().getAge()); //fails

Unfortunately, you can't do that with an ArgumentCaptor.
The captor only stores a reference to the argument; in this case, it stores twice a reference to the same object, person.
You should try using an Answer, to perform the proper check every time the setPerson method is called.
This mockito issue is related to what you're trying to do.

Can't you just do
verify(mockedList, times(1)).setPerson(eq(5));
verify(mockedList, times(2)).setPerson(eq(6));
Been a while since I used mockito so I think that's the right syntax.
Or do you need to capture the value for some other reason than assertions?

I think it is not possible with Mockito. You may rewrite your code to make it "unit testatble" or much better by writing the test first and the code after in a TDD approach.
However if for some reasons you can't modify your code, it is possible to use PowerMock features. For example PowerMockito.whenNew will allow you to provide a mock of A. But this approach is not recommended.

Related

Unit testing void public methods

I have a class that I am trying to write a few unit tests for, specifically, a void method within the class. Im not entirely sure whether or not the fact that the method is void is of any consequence here, but this is the basic structure of the class.
public class MyClass {
private Map<String,Object> myMap;
public void process(Bucket bucket){
//parses bucket, updates myMap
}
public int getAnswer(String input){
//searches map data
}
}
The basic usage of the class is that the process method is called for each bucket to ingest it’s data, and the getAnswer method returns a summation of sorts about the data that has been processed from the buckets.
I’ve written a few unit tests for the getAnswer method, but since the process method doesn’t return anything, but rather just updates the internal state of my object, is there a way to properly unit test it? Since it’s a public method, I figured that it needed to be unit tested, but haven’t figured out how to do so, independent of the getAnswer method.
We would need more code to answer you in details, but in short the answer is yes, you can and should definitely test it.
process is going to make some side-effects somewhere, right? Either you inject Mockito mocks of the classes/interfaces these side-effects are effected upon, or if you have an in-memory version of them you inject that instead.
In the case of mocks, you'll want to carefully assert that the side-effect methods were called exactly with the right parameters. If you're using an in-memory simulation, you check the state of your in-memory object and check it conforms to what you expected.
For unit testing of process method, I think you can do following:
Verify input bucket can be able to parse based on your method comments.
Exception handling -- if applicable -- if bucket is unable to parse.
For map update / add, you can always check if initial size is changed & valid bucket made successful attempt to add to map. If bucket key already present, you can also verify if size of map remains same.
All above points are based on information provided in original question & it is independent of getAnswer method.

How to mock multiple objects which will return non-null values

I need help in creating mocking two objects simultaneously.
If I set the return value of first mock obj i.e. mockClassA to null, it is working fine. I'm using annotations #Mock, #TestSubject of EasyMock. And if I don't set the first mock expectation's return as null, I'm seeing the following error.
java.lang.IllegalStateException: last method called on mock is not a void method
Here is the code, I'm trying:
EasyMock.expect(mockClassA.getValfromDB()).andReturn(ValA);
EasyMock.replay();
EasyMock.expect(mockoClassB.makeRestCall(EasyMock.anyString())).times(2).andReturn(httpResponse);
EasyMock.replay();
If EasyMock doesn't support mocking multiple objects in a single method, I'm allowed to use Mockito, PowerMockito, EasyMockSupport. Please feel free to suggest me something from those libraries too.
P.S: I already tried using replayall() from EasyMockSupport. But it didn't make any difference.
I could able to debug my code and found that I'm giving the no of times in wrong way.
Changing the line
EasyMock.expect(mockClassB.makeRestCall(EasyMock.anyString())).times(2).andReturn(httpResponse);
EasyMock.replay();
to
EasyMock.expect(mockClassB.makeRestCall(EasyMock.anyString())).andReturn(httpResponse);
EasyMock.expectLastCall().times(2);
EasyMock.replay();
has resolved my issue (Observe expectLastCall.times(2)).
Ref: TutorialsPoint.com
A mock must be passed to the replay() method. So your original code nor the answer are working. However, it is true that the times() must be after the andReturn().
So a correct code would be
expect(mockClassA.getValfromDB()).andReturn(ValA);
expect(mockClassB.makeRestCall(anyString())).andReturn(httpResponse).times(2);
replay(mockClassA, mockClassB);
or this with EasyMockSupport:
expect(mockClassA.getValfromDB()).andReturn(ValA);
expect(mockClassB.makeRestCall(anyString())).andReturn(httpResponse).times(2);
replayAll();
Note that I'm using static imports. It makes the code much more agreeable to the eyes.

How to verify if an argument passed is with correct parameters if that argument's state is changed?

I'm trying to verify the object by using
#Captor
ArgumentCaptor<User> userArgumentCaptor
...//define user with name and jailName - var = user1
...//Call the method under test.
verify(userDao).getName(userArgumentCaptor.capture());
verify(userDai).getJailName(userArgumentCaptor.capture());
assertThat(userArgumentCaptor.getAllValues()).isEqualTo(Arrays.asList(user1user1));
/**
* Notice here that I had to use same object to verify even when I captured it in two different situations.
*/
for the scenario,
User user = new User(); //Object under inspection.
user.setId(); //Changing state here.
userDao.getName(user); //Capture user here.
...
if(someBooleanCondition) {
user.setJailStatus(true); //Changing state here.
userDao.getJailName(user); //Capture user here.
}
While asserting the userArgumentCaptor.getValue(), it is checking the updated value. This actually makes sense since I'm capturing the object not object's state.
But, how do I verify the object's state when it was passed?
I think this is not possible. Even when checking out the very latest version of ArgumentCaptor (mockito 2.7.21 at this point); there is no indication at all to go in that direction.
The purpose respectively service offered by ArgumentCaptor is to collect those parameters used when a method is called.
What you are asking is basically: is there a way to do additional checking at the point when that call happens.
I guess, it could be made possible: the framework would have to allow you to register a callback, that is called whenever a specific method is invoked on a mock object. But that isn't possible today.
The only solution I see - instead of doing
#Mock
YourRealDaoClass theMockedDao
You would have to do
class MockedDaoClass extends YourRealDaoClass {
and then implement such things yourself. So that you can put:
YourRealDaoClass theMockedDao = new MockedDaoClass(...
into your tests. Together with a some other logic to enable the things you need.
In other words: the mocks generated by Mockito do not allow you to do enhanced testing at the point when methods are invoked on mocked objects. If you need that (for example to do a test like: param.getFoo().equals()) then you are back to creating your own stub/mock class.
What you have to do:
carefully check all the methods that the Dao class has
decide which one you need to overwrite, to make sure that they return the values you need to make the mock work with your production code
for the methods that receive those parameters you are interested in: either do checking right there; or collect the values for later checking

How does a Mockito spy know when it is spying?

This code from the documentation is totally baffling me:
List list = new LinkedList();
List spy = spy(list);
when(spy.size()).thenReturn(100); // <--- how does this spy know
// not to call the real method????
//using the spy calls *real* methods
spy.add("one");
spy.add("two");
I get it, Mockito is weird and hardly still in Java. Confusing thing is spy.* has to evaluate fully before it knows whether it's wrapped in a when() or something. How on earth would the first spy.* method not call on the real object but the later ones doe?
According to the documentation the first when(spy.size()).thenReturn(100) will actually invoke the real List.size() method, see: http://mockito.github.io/mockito/docs/current/org/mockito/Mockito.html#13
Each subsequent call of course will then return the mocked result.
If you don't want the real method to be called (e.g. when(spy.get(0)).thenReturn(...) would probably throw an IndexOutOfBoundsException, you have to use this pattern: doReturn(...).when(spy).get(0);
I don't know the exact implementation, but I can take a guess.
The call to spy(...) first proxies the given object and keeps it as a reference to delegate calls.
The call
when(spy.size()).thenReturn(100);
is practically equivalent to
Integer result = spy.size();
OngoingStubbing<Integer> stubbing = when(result); // result is useless
stubbing.thenReturn(100);
The first call to size() is invoked on the proxy. Internally, it can register the call, pushing it, for example, on a static (global) Mockito stack. When you then invoke when(), Mockito pops from the stack, recognizes the call to size() as needing stubbing and performs whatever logic required to do so.
This can explain why stubbing in a multithreaded environment is bad business.

Proper way to compare object in a Unit test

I'm writing unit tests for my grails application, and I realized I don't really know the proper way to assert whether an object is the proper object or not.
For example, given this test:
void testExampleTest() {
mockSession.person = new Person(firstName:'John', lastName:'Doe', middleInitial:'E')
def model = controller.testMethod()
...assertions...
}
and
def testMethod = {
Person currPerson = session.getAttribute("person")
render(view:'view',model:[person:currPerson]
}
how should I make sure that the person object I added to the session is properly being passed in the model? Is it sufficient to use
assertEquals( person,model['person'] )
or because I injected the object myself into the session does it make more sense to use
assertEquals( person.firstName, model['person'].firstName )
assertEquals( person.lastName, model['person'].lastName )
assertequals( person.middleName, model['person'].middleName )
It seems to me that the first way should suffice as long as the object has a properly defined equals method, but I just wanted to see what the conventional way is.
Thanks
Property-by-property comparison needs to be repeated in every test - so it's a good old code duplication, a test smell described in XUnitPatterns. Better have a proper equals().
Of course, you can add an utility method personEquals() or even override Person.equals() in runtime. For mocked class, you will probably have to. I personally stick to shorter code which is just one assertEquals() when possible.
Funny, I and a colleague had a similar discussion today. Our conclusion was that
An advantage of the more laborious attribute-by-attribute comparison is that it reports a specific difference rather than just a "no, they are not equals", and this may be convenient.
Also we did not have control over certain classes, and some of those lacked an equals method.
We intend to investigate whether it's possible to use reflection to implement a comparator, hence removing some of the tedium.
I have found that doing property by property is a little more reliable and gives you a little bit more fine grain control over how something is compared, the down side is it's a little more work to set up and maintain
If equals is defined properly you are right. The problem is, that you might have to first unit test if equals is defined properly (meaning it behaves the way you expect it to).
This might get a little more difficult if you create a mockup for the Person class. In that case you don't care if equals works properly because you only want to check if some attributes are being set/accessed properly. This is why I prefer checking for primitive values if possible and necessary. I find that it makes the tests also more descriptive (although it can become pretty verbose).
In this particular instance, testing the individual properties is only a way for you to identify a specific instance of an object, and it clouds the meaning of the test. What you specifically care about and should assert is that model['person'] is the exact same object as what you initially put in as person:
assertSame(person, model['person'])
Or with Hamcrest, which allows much more expressive assertions overall:
assertThat(model['person'], sameInstance(person))
As you wrote, if the test data has a proper equals method, you can use it. "Proper" here means that it tests the attributes you want to be tested.
I often work with database entities which only compare their ID attribute. With these objects, I need to test each attribute separately to see if they are equal. I wrote a little helper that allows me to write a single assert for many properties, like this:
assertEqualProperties(person, model['person'], "firstName", "lastName", "middleName");
This helper method uses reflection to access the attributes (not directly, I invoke the commons-beans library). In Groovy, there surely is a syntax that does not need explicit reflection. The method reports the first non-equal attribute as a test failure.
In Grails every object is serializable, so you could compare the two using their XML Serializations:
public void compareXML(Object a, Object b)
ByteArrayOutputStream aBaos = new ByteArrayOutputStream();
XMLEncoder aEncoder = new XMLEncoder(aBaos);
aEncoder.writeObject(a);
aEncoder.close();
String xmlA = baos.toString();
ByteArrayOutputStream bBaos = new ByteArrayOutputStream();
XMLEncoder bEncoder = new XMLEncoder(bBaos);
bEncoder.writeObject(b);
bEncoder.close();
String xmlB = bBaos.toString();
assertEquals(xmlA, xmlB);
}
If you're working in eclipse, you'll get a great textual comparison of the two XML strings showing all of the differences.
I use assertSame(). Comparing field by field is way more work than necessary - you mocked the data, so just assert that the mocked values are properly returned.

Categories

Resources