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 org.junit.Assert.fail; 8 9 import org.junit.Test; 10 import org.mockito.Mockito; 11 import org.mockito.invocation.InvocationOnMock; 12 import org.mockito.stubbing.Answer; 13 14 import java.util.concurrent.ExecutorService; 15 import java.util.concurrent.Executors; 16 import java.util.concurrent.TimeUnit; 17 import java.util.concurrent.atomic.AtomicInteger; 18 19 //see bug 190 20 public class ShouldNotDeadlockAnswerExecutionTest { 21 22 @Test failIfMockIsSharedBetweenThreads()23 public void failIfMockIsSharedBetweenThreads() throws Exception { 24 Service service = Mockito.mock(Service.class); 25 ExecutorService threads = Executors.newCachedThreadPool(); 26 AtomicInteger counter = new AtomicInteger(2); 27 28 // registed answer on verySlowMethod 29 30 Mockito.when(service.verySlowMethod()).thenAnswer(new LockingAnswer(counter)); 31 32 // execute verySlowMethod twice in separate threads 33 34 threads.execute(new ServiceRunner(service)); 35 threads.execute(new ServiceRunner(service)); 36 37 // waiting for threads to finish 38 39 threads.shutdown(); 40 41 if (!threads.awaitTermination(1000, TimeUnit.MILLISECONDS)) { 42 // threads were timed-out 43 fail(); 44 } 45 } 46 47 @Test successIfEveryThreadHasItsOwnMock()48 public void successIfEveryThreadHasItsOwnMock() throws Exception { 49 Service service1 = Mockito.mock(Service.class); 50 Service service2 = Mockito.mock(Service.class); 51 ExecutorService threads = Executors.newCachedThreadPool(); 52 AtomicInteger counter = new AtomicInteger(2); 53 54 // registed answer on verySlowMethod 55 56 Mockito.when(service1.verySlowMethod()).thenAnswer(new LockingAnswer(counter)); 57 Mockito.when(service2.verySlowMethod()).thenAnswer(new LockingAnswer(counter)); 58 59 // execute verySlowMethod twice in separate threads 60 61 threads.execute(new ServiceRunner(service1)); 62 threads.execute(new ServiceRunner(service2)); 63 64 // waiting for threads to finish 65 66 threads.shutdown(); 67 68 if (!threads.awaitTermination(500, TimeUnit.MILLISECONDS)) { 69 // threads were timed-out 70 fail(); 71 } 72 } 73 74 static class LockingAnswer implements Answer<String> { 75 76 private AtomicInteger counter; 77 LockingAnswer(AtomicInteger counter)78 public LockingAnswer(AtomicInteger counter) { 79 this.counter = counter; 80 } 81 82 /** 83 * Decrement counter and wait until counter has value 0 84 */ answer(InvocationOnMock invocation)85 public String answer(InvocationOnMock invocation) throws Throwable { 86 counter.decrementAndGet(); 87 88 while (counter.get() != 0) { 89 Thread.sleep(10); 90 } 91 92 return null; 93 } 94 95 } 96 97 static class ServiceRunner implements Runnable { 98 99 private Service service; 100 ServiceRunner(Service service)101 public ServiceRunner(Service service) { 102 this.service = service; 103 } 104 run()105 public void run() { 106 service.verySlowMethod(); 107 } 108 109 } 110 111 interface Service { 112 verySlowMethod()113 String verySlowMethod(); 114 115 } 116 117 } 118 119