Verifiying time between calls with mockito - java

I've read a lot of documentation, examples on the net, and still have no idea of how to do it. (if it could be done).
I need to test a method in a object called by other thread and it has a requirement of time. So my original idea was creating a spy, override the method and do the task, but the problem is, I can't access test method variables from the spy. So I can't get the value returned from System.currentTimeMillis() from the test method and proccess it to get the difference within times.
I will write some abstract code describing the situation so you could understand better the situation.
#Test
public void test()
{
Objectspied spy = Mockito.spy(new Objectspied(Parameters p));
long[] timesRetrieved = new long[numberOfCallsIExpect];
//here goes the tricky part
Mockito.doAnswer(new Answer<void>(){
#override
public methodCalledFromAnotherThread(int index)
{
//what i wish to do but can't do it
timesRetrieved[i] = System.currentTimeMilis();
}
}
).when(spy).methodCalledFromAnotherThread(anyInt);
//here initialize the thread who call it
//then proccess al time diferences and get sure they are what i've expected
}
public class AnotherThread
{
ObjectSpied reference;
public void run()
{
for (int i=0;i<repeat;i++)
{
reference.methodCalledFromAnotherThread(i);
Thread.sleep(1000);
}
}
}
I'm new to Mockito so i know syntax is totally wrong but i can fix that by myself, all i need to know is:
Is there any way to do it with Mockito?
If so, can you point me to the right direction?

You should be fine this way. Just make sure:
1) You mark the array as final
2) Properly implement the answer interface method
final long[] timesRetrieved = new long[size];
Mockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
int index = invocationOnMock.getArgumentAt(0, Integer.class);
timesRetrieved[index] = System.currentTimeMillis();;
return null;
}
}
).when(spy).methodCalledFromAnotherThread(Mockito.anyInt());

Related

Skip method call in junit test case using EasyMock?

I am writing a test case for "headersection()" method. Inside this method, it is calling a constructor of another class, let's say "InformationHeader.java" class. Inside this constructor, it will invoke one method called as "makepage()". Again "makepage()" method will invoke another "createpage()" method.
I wanted to skip the method call to "createpage()" in my test case. Please suggest how to achieve this scenario?
private void headersection(Object child) {
headerobject = new InformationHeader(parameter_1, parameter_2, parameter_3, parameter_4);
//lines of code
}
//InformationHeader.java
public InformationHeader(parameter_1, parameter_2, parameter_3, parameter_4) {
//lines of code
makepage();
//lines of code
}
public final void makepage() {
//lines of code
createpage(); //I wanted to skip this method call
}
Any help would be appreciated
Thanks
I hope I got your question, but as I mentioned in my comment, you could change the method a bit and create a method which could be mocked.
void headersection(Object child) {
headerobject = getInformationHeader(/*parameter*/)
//lines of code
}
InformationHeader getInformationHeader(/*parameter*/) {
return new InformationHeader(parameter_1,parameter_2,parameter_3,parameter_4);
}
I don't know your class name in which the headersection mehtod is stored, lets say SectionService. Now, you could use Mockito to create a so called spy
#InjectMock
SectionService serviceToTest;
SectionService spyServiceToTest = Mockito.spy(serviceToTest);
InformationHeader spyInformationHeader = Mockit.spy(new InformationHeader(/*parameter*/));
Now you can mock a call inside of the tested class:
Mockito.doReturn(spyInformationHeader).when(spyServiceToTest).getInformationHeader(//parameter);
Mockiot.doNothing().when(spyInformationHeader).createpage();
Here is a stackoverflow question which is dealing with spy calls and
here is the Mockito documentation.
I hope this helps, greetings Matthias
The answer using spies doesn't work. The new InformationHeader(/*parameter*/) will call createpage. You will have the same problem with EasyMock.
The problem is that you can't mock a method before creating a partial mock. So when the constructor is calling a method, it doesn't work.
I would probably rethink my design if I was you. But not having the full picture, I can't give advice on that.
Keeping the current design, the easiest is actually to do a manual mock. It goes like this.
public class MyTest extends EasyMockSupport {
#Test
public void test() {
InformationHeader header = new InformationHeader("a", "b", "c", "d") {
#Override
public void createpage() {
// do nothing
}
};
ToTest toTest = partialMockBuilder(ToTest.class)
.withConstructor()
.addMockedMethod("createHeader")
.mock();
expect(toTest.createHeader()).andReturn(header);
replayAll();
toTest.headersection(null);
}
}
class ToTest {
void headersection(Object child) {
InformationHeader headerobject = createHeader();
}
InformationHeader createHeader() {
return new InformationHeader("a", "b", "c", "d");
}
}
class InformationHeader {
public InformationHeader(String p1, String p2, String p3, String p4) {
makepage();
}
public final void makepage() {
createpage();
}
public void createpage() {
throw new RuntimeException("Should not be called");
}
}

Unit testing method that uses callback and SynchronousQueue to track results

I'm using Mockito to test a method that internally makes a networking call and returns a value based on the result of the networking call. This method uses a SynchronousQueue to wait for the result, and the result is set by the callback for the networking call:
HelperClass helperClassObject = new HelperClassObject();
...
public SomeResultCode methodWithNetworkCall() {
SynchronousQueue<SomeResultCode> resultQueue = new SynchronousQueue<>();
// some condition checking code
helperClassObject.makeNetworkCall(new GenericCallback() {
#Override
public void onSuccess(JSONObject response) {
resultQueue.offer(SomeResultCode.SUCCESS);
}
#Override
public void onFailure(VolleyError error) {
resultQueue.offer(SomeResultCode.FAILURE);
}
});
SomeResultCode resultCode = null;
try {
resultCode = resultQueue.poll(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
}
return resultCode == null ? SomeResultCode.FAILURE : resultCode;
}
In one of my unit test methods I'm trying to verify that SUCCESS is returned upon successful network call. I've tried using ArgumentCaptor and doAnswer to trigger the callback's onSuccess. However, the method is returning FAILURE. I put a breakpoint in the onSuccess, and it looks like when I use the ArgumentCaptor way the onSuccess is triggered AFTER the poll has timed out. When I use the doAnswer way, I see onSuccess called during the setup (doAnswer.when) but not after I actually call the method. What am I doing wrong?
EDIT
Stepping through the code again, it looks like answer is called from within the method I'm testing (i.e. when I call testObject.methodWithNetworkCall during my test), NOT during setup. So it is doing exactly what it is supposed to do: responding with onSuccess. But it is responding with onSuccess BEFORE poll is called. So it seems the problem is not that answer and mocking in general is not working/set up wrong, it is an issue with testing with SynchronousQueue.
Here is my test code:
public class TestClassUnitTest {
TestClass sut;
HelperClass helperClassObject = mock(HelperClass.class);
#Before
public void setup() {
sut = new TestClass();
injectField(sut, "helperClassFieldName", helperClassObject);
}
public void injectField(Object testObject, String fieldName, T mockToInject) {
// some code using reflection to inject the mock object into the test object
}
#Test
public void testMethodWithNetworkCallWithCaptor() {
ArgumentCaptor<GenericCallback> captor = ArgumentCaptor.forClass(GenericCallback.class);
SomeResultCode result = sut.methodWithNetworkcall();
verify(helperClassObject, times(1)).makeNetworkCall(captor.capture());
captor.getValue().onSuccess(new JSONObject());
Assert.assertEquals(SomeResultCode.SUCCESS, result);
}
#Test
public void testMethodWithNetworkCallWithDoAnswer() {
doAnswer(new Answer(){
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
((GenericCallback)invocation.getArguments()[0]).onSuccess(new JSONObject());
return null;
}
}).when(helperClassObject).makeNetworkCall(any(GenericCallback.class));
SomeResultCode result = sut.methodWithNetworkcall();
Assert.assertEquals(SomeResultCode.SUCCESS, result);
}
}
It looks like you're not replacing your HelperClassObject in your system-under-test, or at least you haven't shown us where you have. The mock returned by Mockito.mock (or #Mock or spy or #Spy) doesn't apply to every instance of the class you pass in; it just creates a single instance. You have to make sure to set the instance (HelperClassObject here) in your system-under-test, possibly by passing it in as a constructor parameter, setting the instance as a field, or setting it using a setter method. If you leave it as new HelperClassObject() as you've shown us, there's no way Mockito will be able to help you.
Your reference to "onSuccess called during the setup (doAnswer.when)" worries me a little bit, because if you've created a mock using Mockito.mock, there should be no reason Mockito would actually call your Answer during setup. This leads me to believe that your HelperClassObject or makeNetworkcall method can't be mocked, possibly from having limited visibility, or because they're marked static or final. Mockito effectively works by writing a custom subclass of the class you're mocking, so make sure the classes and methods you're mocking are public and non-final to ensure they're overridable. (It is possible to mock protected or package-private methods, but certain versions of Mockito have complications with certain code structures. Let's rule that out first.)
After you make sure that the class is mockable and that it's using the mocked HelperClassObject instance you pass in, you'll be able to move forward. You'll want to pursue the doAnswer structure: The ArgumentCaptor version won't work, because if your methodWithNetworkcall blocks and waits for a result, then you'll get a FAILURE return value before you ever get a chance to verify and call your callback. (That explains the timeout.) In other cases where your method-under-test can return first, the ArgumentCaptor solution will be more practical for you.
In this case using doAnswer IS the correct approach. The issue is with the way SynchronousQueue worked: it expects multi-threaded usage of this queue:
A blocking queue in which each insert operation must wait for a corresponding remove operation by another thread, and vice versa.
But in this testing case the test runs on a single thread.
Solution: mock the SynchronousQueue, and use doAnswer to get offer() and poll() to push/pop result onto a LinkedList. In the process, I also moved the SynchrnousQueue local variable resultQueue out of methodWithNetworkCall() and made it an instance member. Updated test code below:
public class TestClassUnitTest {
TestClass sut;
private LinkedList testQueue = new LinkedList();
private SynchronousQueue<SomeResultCode> resultQueueMock = mock(SynchronousQueue.class);
private HelperClass helperClassMock = mock(HelperClass.class);
#Before
public void setup() {
sut = new TestClass();
injectField(sut, "resultQueue", resultQueueMock);
injectField(sut, "helperClassFieldName", helperClassMock);
}
public void injectField(Object testObject, String fieldName, T mockToInject) {
// some code using reflection to inject the mock object into the test object
}
#Test
public void testMethodWithNetworkCallWithDoAnswer() {
doAnswer(new Answer(){
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
((GenericCallback)invocation.getArguments()[0]).onSuccess(new JSONObject());
return null;
}
}).when(helperClassMock).makeNetworkCall(any(GenericCallback.class));
mockQueue();
SomeResultCode result = sut.methodWithNetworkCall();
Assert.assertEquals(SomeResultCode.SUCCESS, result);
}
private void mockQueue() {
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
testQueue.push(((SchedulableJob.Result)invocation.getArguments()[0]));
return true;
}
}).when(resultQueueMock).offer(any());
try {
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
if (testQueue.size() > 0) {
return testQueue.pop();
} else {
return null;
}
}
}).when(resultQueueMock).poll(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
}
}
}

Mockito void doAnswer correct usage & purpose

Today I learned about Mockito and while playing around with it I found something I do not understand.
Say I would like to test the following piece of code:
public void stop(boolean showMessage) {
if(executor != null && !executor.isShutdown() && this.isRunning) {
if(showMessage) {
View.getSingleton().showMessageDialog(Constant.messages.getString("sessionchecker.stopmessage"));
}
executor.shutdownNow();
executor = null;
extension.getCountdownTimer().stopCountdown();
this.isRunning = false;
this.usersReady.clear();
}
}
Since the stop method is a void I would need to call doAnswer (If I understand correctly).
So I tried the following:
#Test
public void testStopIsRunningFalse() {
Mockito.when(controller.isRunning()).thenReturn(true); // Mock a running service
Mockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
if(controller.isRunning()) {
// Normally would actually shut down service
Mockito.when(controller.isRunning()).thenReturn(false); // Service should stop
}
return null;
}
}).when(controller).stop(false);
controller.stop(false);
boolean expected = false;
assertEquals(expected, controller.isRunning());
}
I, however, do not understand what the purpose of a test like this would be. Why would I test it like this since this will never fail (the parameter isRunning is being set as I would expect it to be).
Basically I only need to test the state of certain fields (isRunning and executor for example). These fields do not have public getters or setters however..
Therefore, I think I misunderstand the usage of the deAnswer. Could someone help me out?
If I understand your code example, it appears you are mocking the object you want to test, which is a no-no 99.9% of the time. You generally only want to mock direct collaborators of the class you are testing. Collaborators consist of things such as injected services (or other injected fields), and arguments of the method you are testing -- essentially anything that represents initial state of your class under test before you invoke the method being tested.

JMockIt Mock not being applied using Faking : Mocking parents of mocked classes

Ok... I have an answer... see below. Thanks to everyone that helped. I have updated the title as well to better reflect the issues.
UPDATE2: The constructor of the parent class of ClassNotUnderTest (which has parameters) is being called with null parameters, which in turn calls it's parent with the same null parameters, which ends up causing a null exception.
I have tried:
Making mocks of both parents, with only the constructor mocked and used one or both of them when trying out the test. The MockClassNotUnderTest still calls the real constructors.
I tried using the #Mocked annotation in the parameter list for the test method, because I don't really want anything back from those parents... Nope. Causes some other error I don't understand.
I tried putting a super(someParams) call in my $init function, but that won't compile.
HEEEEELLLLLPPPPP!!!!
UPDATE:
Ok, the root of my problem is not the implementation as shown below, but with the mock itself. When the MockClassNotUnderTest makes it's constructor call, it is calling the constructor of the real parent of ClassNotUnderTest. I tried also mocking ParentofClassNotUnderTest, but that just caused NullPointerExceptions... sigh. Still searching, I will post updates as they occur. Any suggestions are welcome.
I am fairly new to JMockIt, but my Java skills are not bad. I am trying to mock a dependency class of the class under test. It appears that the either the real method is being called, or maybe it is the super class (more likely). So any ideas on what I am doing wrong?
Now I know some might comment on how I am setting the error parameter, and how that might be applied etc, and I welcome the comments, but the main problem is that this code is not being mocked properly/at all as far as I can see.
To answer a few questions up front... Yes I searched here, and yes I reviewed the tutorials/documentation at the JMockIt website... had both open as I wrote the code in the first place.
I have several similar situations to resolve, so any help is much appreciated. Thanks in advance.
Something like this:
public ClassUnderTest {
public someMethodUnderTest (){
<blah blah setup stuff>
try{
somevar = new ClassNotUnderTest(someParamA, someParamB, someParamC);
} catch(SomeExceptionA sea) {
System.out.printline("Go boom");
} <more catches here>
}
}
My test/mock classes are as follows (JUnit4/JMockIt):
public class TestClassUnderTest{
ClassUnderTest cut;
<Before method and constructor with some setup code for cut>
#Test public void test_someMethodUnderTest(){
MockClassNotUnderTest notUnderTest = new MockClassNotUnderTest();
notUnderTest.error = 1;
try{
testResults = cut.someMethodUnderTest();
} catch( SomeExceptionA sea) {
<test that it went boom>
}
}
public class MockClassNotUnderTest extends MockUp<ClassNotUnderTest> {
public int error = 4;
#Mock
public void $init(someParamA, someParamB, someParamC) throws SomeExceptionA, SomeExceptionB, SomeExceptionC {
if(error == 0) { thrown new SomeExeptionA(); }
else if(error == 1) { thrown new SomeExeptionB(); }
else if(error == 2) { thrown new SomeExeptionC(); }
else { }
}
}
}
My expectation would be that the new MockClassNotUnderTest() you are initializing in the test method does not share state with the new ClassNotUnderTest() that you are initializing in the production code.
Try making your error a static field, so that it is shared across objects being faked.
I have written a sample test case showing that your comment below is correct. I cannot replicate your problem unless you post real code... Here is my test:
public class FakeTest {
public static class Foo {
public void doSomething() {
try {
Bar b = new Bar(73);
} catch (Throwable t) {
System.out.println("Got a " + t.getClass());
}
}
}
public static class Bar {
private Integer param;
public Bar(Integer parameter) {
System.out.println("Got a real bar with param " + parameter);
this.param = parameter;
}
}
public static class MockBar extends MockUp<Bar> {
public int error = 4;
#Mock
public void $init(Integer parameter) {
System.out.println("Initing fake with parameter " + parameter);
if (error==1) {
throw new IllegalAccessError();
}
}
}
#Test
public void fakeTest() throws Exception {
System.out.println("Testing...");
MockBar mb = new MockBar();
mb.error=1;
Foo f = new Foo();
f.doSomething();
}
}
The output, as you would expect, is
Testing...
Initing fake with parameter 73
Got a class java.lang.IllegalAccessError
Think of this as a part II to the answer provided above.
What is provided there will successfully mock out a constructor. The root of my issue lay in the fact that my original MockClassNotUnderTest was calling the constructor of the REAL parent of ClassNotUnderTest. In faking this was not completely unexpected, so I made a mock of the parent... which the mock never called.
My original setup of the mocks (the MockBar mb = new MockBar() above) would have a line above it to setup the parent mock, which looked exactly the same, but with a different name. So I might have:
MockBarParent mbp = new MockBarParent();
MockBar mb = new MockBar();
mb.error = 1;
This did not work obviously... here's what did work:
Mockit.setUpMock(new MockBarParent());
MockBar mb = new MockBar();
mb.error = 1;
Now as for the why, I am not sure, but I can tell you this is how you setup a static mock.
One final word. These mocks will stay in memory when you do this. Be sure to call Mockit.tearDownMocks() before leaving the test function or it will persist into other tests. JUnit does not run tests in order, so this can cause all kinds of fun errors.
THANKS AGAIN FOR THE HELP!!!!! #dcsohl and Nicolas

How to rectify junit giving assertion error as expected:1 and actual:0?

I have a junit method like this :
public void testMyStuff() {
IMockBuilder<BackingBean> builder = createMockBuilder(BackingBean.class);
builder.addMockedMethod("getMyFacesContextSessionMap");
BackingBean bean = builder.createMock();
MyVO MyVO = new MyVO();
List<MyVO> MyVOList = new ArrayList<MyVO>();
HttpServletRequest req = createMock(HttpServletRequest.class);
bean.setHttpServletRequest(req);
MyVOList.add(buildMyVO());
expect(bean.getMyFacesContextSessionMap()).andReturn(
new HashMap<String, Object>());
expect(ac.getBean("MyService")).andReturn(service);
expect(MyFacade.getMyStuff(MyVO)).andReturn(MyVOList);
expect(bean.getMyFacesContextSessionMap()).andReturn(
new HashMap<String, Object>());
replay(bean, MyFacade);
bean.setService(service);
String returnString = bean.myStuff();
assertEquals("myNo", returnString);
}
When i run it as junit in eclipse i get this error :
java.lang.AssertionError:
Unexpected method call MyFacadeLocal.getMyStuff(MyVO#8c64cdd8):
MyFacadeLocal.getMyStuff(MyVO#d79a467f): expected: 1, actual: 0
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:44)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:85)
at $Proxy1.getMyStuff(Unknown Source)
I am not understanding how to rectify this . Can some one help me plz ?
Example of an ArgumentMatcher:
public class CollectionCountMatcher implements IArgumentMatcher
{
private int expectedCount;
public CollectionCountMatcher(int count) {
super();
this.expectedCount = count;
}
public boolean matches(Object actual) {
return (actual instanceof Collection)
&& ((Collection) actual).size() == expectedCount;
}
public static final Integer eqObject(Integer inValue) {
EasyMock.reportMatcher(new CollectionCountMatcher (inValue));
return inValue;
}
public void appendTo(StringBuffer buffer) {
buffer.append("collectionContains(" + expectedCount + ")");
}
}
You create an MyVOMatcher and you call your mock method like this:
expect(MyFacade.getMyStuff(MyVOMatcher.eqObject(MyVO))).andReturn(MyVOList);
EDIT: Or what you can also do, but this way of working is less strict and doesn't check for different objects is doing it like this:
expect(MyFacade.getMyStuff(EasyMock.anyObject(myVO.class))).andReturn(MyVOList);
This will work for sure, but off course you can pass every possible argument, as long as it's of the type MyVO
This means that the method
getMyStuff
with as argument MyVO is never called in your backing bean. Check if that method is really called. If that's the case, implement the equals() and hashCode() methods for MyVO since probably it's not recognized as the same element since it's a different object.
The error message just tells you you expect the method with the EXACT parameter that you specify, but that it wasn't encountered...
I guess it's because getMyStuff is a static method. Mocking static methods is not ideal with EasyMock. Maybe consider Powermock and if you want to do it in EasyMock anyway, you can try the following:
You could move the static call to a method, override this method in the instantiation of the tested class in the test class, create a local interface in the test class and use its method in the overidden method:
private interface IMocker
{
List<MyVO> getMyStuff(MyVO myVO);
}
IMocker imocker = EasyMock.createMock(MyFacade.class);
...
#Override
List<MyVO> getMyStuff(MyVO myVO)
{
imocker.getMyStuff(myVO);
}
...
EasyMock.expect(imocker.getMyStuff(EasyMock.anyObject(myVO.class))).andReturn(true);

Categories

Resources