blob: 0b9ef35351638123f451288168993a72eac89d6a [file] [log] [blame]
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockitousage.bugs;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
//see bug 190
public class ShouldNotDeadlockAnswerExecutionTest {
@Test
public void failIfMockIsSharedBetweenThreads() throws Exception {
Service service = Mockito.mock(Service.class);
ExecutorService threads = Executors.newCachedThreadPool();
AtomicInteger counter = new AtomicInteger(2);
// registed answer on verySlowMethod
Mockito.when(service.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
// execute verySlowMethod twice in separate threads
threads.execute(new ServiceRunner(service));
threads.execute(new ServiceRunner(service));
// waiting for threads to finish
threads.shutdown();
if (!threads.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
// threads were timed-out
Assert.fail();
}
}
@Test
public void successIfEveryThreadHasItsOwnMock() throws Exception {
Service service1 = Mockito.mock(Service.class);
Service service2 = Mockito.mock(Service.class);
ExecutorService threads = Executors.newCachedThreadPool();
AtomicInteger counter = new AtomicInteger(2);
// registed answer on verySlowMethod
Mockito.when(service1.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
Mockito.when(service2.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
// execute verySlowMethod twice in separate threads
threads.execute(new ServiceRunner(service1));
threads.execute(new ServiceRunner(service2));
// waiting for threads to finish
threads.shutdown();
if (!threads.awaitTermination(500, TimeUnit.MILLISECONDS)) {
// threads were timed-out
Assert.fail();
}
}
static class LockingAnswer implements Answer<String> {
private AtomicInteger counter;
public LockingAnswer(AtomicInteger counter) {
this.counter = counter;
}
/**
* Decrement counter and wait until counter has value 0
*/
public String answer(InvocationOnMock invocation) throws Throwable {
counter.decrementAndGet();
while (counter.get() != 0) {
Thread.sleep(10);
}
return null;
}
}
static class ServiceRunner implements Runnable {
private Service service;
public ServiceRunner(Service service) {
this.service = service;
}
public void run() {
service.verySlowMethod();
}
}
interface Service {
String verySlowMethod();
}
}