• 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 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 {
getValue(Integer param)29         Integer getValue(Integer param);
30 
getValues(Integer param)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
setUp()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      */
getConflictingRunnable(final ToMock toMock)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