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