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