Home | History | Annotate | Download | only in bugs
      1 /*
      2  * Copyright (c) 2007 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 package org.mockitousage.bugs;
      6 
      7 import org.junit.Before;
      8 import org.junit.Ignore;
      9 import org.junit.Test;
     10 
     11 import java.util.LinkedList;
     12 import java.util.List;
     13 import java.util.concurrent.Executor;
     14 import java.util.concurrent.Executors;
     15 import java.util.concurrent.RejectedExecutionException;
     16 
     17 import static java.util.Collections.synchronizedList;
     18 import static org.junit.Assert.fail;
     19 import static org.mockito.Mockito.mock;
     20 import static org.mockito.Mockito.when;
     21 
     22 @Ignore
     23 public class MultithreadedStubbingHalfManualTest {
     24 
     25     /**
     26      * Class with two methods, one of them is repeatedly mocked while another is repeatedly called.
     27      */
     28     public interface ToMock {
     29         Integer getValue(Integer param);
     30 
     31         List<Integer> getValues(Integer param);
     32     }
     33 
     34     /**
     35      * Thread pool for concurrent invocations.
     36      */
     37     private Executor executor;
     38 
     39     private List<Exception> exceptions = synchronizedList(new LinkedList<Exception>());
     40 
     41     @Before
     42     public void setUp() {
     43         this.executor = Executors.newSingleThreadExecutor();
     44     }
     45 
     46     /**
     47      * The returned runnable simply calls ToMock.getValues(int).
     48      *
     49      * @param toMock The mocked object
     50      * @return The runnable.
     51      */
     52     private Runnable getConflictingRunnable(final ToMock toMock) {
     53         return new Runnable() {
     54             public void run() {
     55                 while (true) {
     56                     try {
     57                         Thread.sleep((long) (Math.random() * 10));
     58                     } catch (InterruptedException e) {
     59                     }
     60                     if (!toMock.getValues(0).isEmpty()) {
     61                         fail("Shouldn't happen, were just making sure it wasn't optimized away...");
     62                     }
     63                 }
     64             }
     65         };
     66     }
     67 
     68     @Test
     69     //this problem shows at 4 out of 5 executions
     70     //it is not strictly a bug because Mockito does not support simultanous stubbing (see FAQ)
     71     //however I decided to synchronize some calls in order to make the exceptions nicer
     72     public void tryToRevealTheProblem() {
     73         ToMock toMock = mock(ToMock.class);
     74         for (int i = 0; i < 100; i++) {
     75             int j = i % 11;
     76 
     77             // Repeated mocking
     78             when(toMock.getValue(i)).thenReturn(j);
     79             //TODO make it also showing errors for doReturn()
     80 //            doReturn(j).when(toMock).getValue(i);
     81 
     82             while (true) {
     83                 try {
     84                     // Scheduling invocation
     85                     this.executor.execute(getConflictingRunnable(toMock));
     86                     break;
     87                 } catch (RejectedExecutionException ex) {
     88                     fail();
     89                 }
     90             }
     91 
     92             try {
     93                 Thread.sleep(10 / ((i % 10) + 1)); //NOPMD
     94             } catch (InterruptedException e) {
     95             }
     96         }
     97     }
     98 }
     99