Problem to mock Callable call()

5,185 views
Skip to first unread message

mikaelpe...@gmail.com

unread,
Jul 4, 2013, 9:48:29 AM7/4/13
to moc...@googlegroups.com
Hi,

I have the following class ( see below). What I want to do is to make sure that I can run more than one poll in parallel.
Each time I execute the test case then I I get a NullPointerException. I can see why since it evaluates the checkState().
How can I mock call in Callable? I just want it to return true after a specific time.

br,

//mike

public class Poll {
   
    private static ExecutorService executor = Executors.newFixedThreadPool(10);
    private static Logger logger = LoggerFactory.getLogger(Poll.class);
   
   
    public boolean poll( long timeout, long period){
      
        boolean isSuccessful = false;
        Future<Boolean> future = executor.submit(new StateTask(period));
       
        try {

            isSuccessful = future.get(timeout, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            future.cancel(true);
            throw new TacApiException("We got an exception " + e.getCause(), e);
        }
   
        return isSuccessful;
    }
   
}


In my StateTask ( a Callable) I have:

@Override
    public Boolean call() throws Exception {
        while (!condition) {
            // wait before we check it
            Thread.sleep(period);
            checkState();
        }
        return condition;
    }



My Test class is:

    @SuppressWarnings("unchecked")
    @Test
        public void testCanIsEnabledRunInParallell() throws Exception{
             final int THREAD_TIME_OUT = 10000;
         
             final int TOTAL = 4;
            
             // expectations
            when(cppNodeMock.getManagedObjectHandler()).thenReturn(managedObjectHandlerMock);
            when(executorServiceMock.submit(isA(Callable.class)))
                            .thenReturn(futureMock);
            when(futureTaskMock.get(anyInt(),isA(TimeUnit.class))).thenReturn(true);
                       
            // run
            boolean oneEnabled = myPoll.poll(THREAD_TIME_OUT, TOTAL);
            boolean twoEnabled = myPoll.poll(THREAD_TIME_OUT, TOTAL);
           
           
           
        }

Eric Lefevre-Ardant

unread,
Jul 5, 2013, 3:05:33 AM7/5/13
to moc...@googlegroups.com
Why do you need to wait for some time before getting a response?

Mocks are certainly not what you should look at if you want to simulate complex behavior such as something that changes state over time. Technically, it might be possible using an Answer, but I don't see how it is easier than alternatives. Here are some ideas.

Option 1:
In your test, I see
  when(executorServiceMock.submit(new StateTask(10000))).thenReturn(futureMock)
This might work provided your executorService is mockable, that is it can be passed by the test to the code under test (to the constructor, for example).
Then, you might configure your futureMock as follows:
  when(futureMock.get(10000,TimeUnit.MILLISECONDS)).thenReturn(true);

This will simulate a behavior where the future immediately returns true. This still makes sense, because the actual behavior of your Callable does not need to be verified (you can do that in a separate StateTaskTest).
You might also add a test that checks what happens then futureMock.get() returns false.

Option 2:
Do not use mock. Just run your code pretty much as is (maybe mock just the checkState() part). Yes, it will take longer to run (you might want to configure the period from the test), but that seems to be exactly what you are trying to do.

Option 3:
Use an answer.

  when(futureMock.get(10000,TimeUnit.MILLISECONDS)).thenAnswer(new Answer() {
     Object answer(InvocationOnMock invocation) {
         Thread.sleep(10000);
         return true;
     }
 })

To be honest, I don't see how that solution helps more than the others.



--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at http://groups.google.com/group/mockito.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages