/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit; import java.awt.*; import java.util.concurrent.*; import javax.swing.*; import org.junit.*; import org.junit.runners.*; import static org.junit.Assert.*; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public final class MultiThreadedExpectationsTest { static class Collaborator { int doSomething() { return -1; } void doSomethingElse() {} static Dependency createDependency() { return new Dependency(); } } @Mocked Collaborator mock; void useMockedCollaboratorFromWorkerThread() { Thread worker = new Thread() { @Override public void run() { mock.doSomethingElse(); } }; worker.start(); try { worker.join(); } catch (InterruptedException ignore) {} } @Test public void useMockedObjectFromWorkerThreadWhileVerifyingExpectation() { mock.doSomething(); mock.doSomething(); new Verifications() {{ mock.doSomething(); useMockedCollaboratorFromWorkerThread(); times = 2; }}; } @Test public void useMockedObjectFromWorkerThreadWhileRecordingAndVerifyingExpectation() { new Expectations() {{ mock.doSomething(); useMockedCollaboratorFromWorkerThread(); result = 123; }}; assertEquals(123, mock.doSomething()); mock.doSomethingElse(); new VerificationsInOrder() {{ useMockedCollaboratorFromWorkerThread(); mock.doSomething(); mock.doSomethingElse(); }}; } @Test public void useMockedObjectFromWorkerThreadWhileRecordingStrictExpectation() { new StrictExpectations() {{ mock.doSomething(); useMockedCollaboratorFromWorkerThread(); result = 123; }}; assertEquals(123, mock.doSomething()); } @Test public void executeInvalidExpectationBlockThenReplayRecordedExpectationFromAnotherThread() throws Exception { try { new Expectations(Runnable.class) {}; fail(); } catch (IllegalArgumentException ignore) {} new Expectations() {{ mock.doSomething(); }}; Thread task = new Thread() { @Override public void run() { mock.doSomething(); } }; task.start(); task.join(); } static class Dependency { void doSomething() {} static void doSomethingElse() {} } @Test public void verifyInvocationsReplayedInAnotherThreadWhoseClassIsNoLongerMocked_part1( @Mocked final Dependency dep, @Mocked final Graphics2D g2D, @Mocked final Runnable runnable) { new Thread() { @Override public void run() { dep.doSomething(); g2D.dispose(); runnable.run(); Dependency.doSomethingElse(); } }.start(); } @Test public void verifyInvocationsReplayedInAnotherThreadWhoseClassIsNoLongerMocked_part2() throws Exception { Thread.sleep(10); new FullVerifications() {}; } static final class ClassWithFinalizeMethod { static boolean finalized; static Dependency dependencyCreated; static int valueReturnedFromRealImplementation; @Override @SuppressWarnings({"FinalizeDeclaration", "FinalizeDoesntCallSuperFinalize"}) protected void finalize() { // Calls to mocked methods from a "Finalizer" thread should be ignored, executing the original implementation: dependencyCreated = Collaborator.createDependency(); valueReturnedFromRealImplementation = new Collaborator().doSomething(); finalized = true; } } @Test public void callMockedMethodFromFinalizeMethodExecutedInFinalizerThread() { // Forces the finalize() method to eventually be called: while (!ClassWithFinalizeMethod.finalized) { new ClassWithFinalizeMethod(); System.gc(); System.runFinalization(); } assertNotNull(ClassWithFinalizeMethod.dependencyCreated); assertEquals(-1, ClassWithFinalizeMethod.valueReturnedFromRealImplementation); } public interface APublicInterface { boolean doSomething(); } @Test public void invokeMethodOnMockedPublicInterfaceFromEDT(@Mocked final APublicInterface mock) throws Exception { new Expectations() {{ mock.doSomething(); result = true; }}; SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertFalse(mock.doSomething()); } }); assertTrue(mock.doSomething()); } public abstract static class AnAbstractClass { public abstract boolean doSomething(); } @Test public void invokeMethodOnMockedAbstractClassFromEDT(@Mocked final AnAbstractClass mock) throws Exception { new Expectations() {{ mock.doSomething(); result = true; }}; SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertFalse(mock.doSomething()); } }); assertTrue(mock.doSomething()); } @Test public void invokeMethodOnMockedGenericInterfaceFromEDT(@Mocked final Callable<Boolean> mock) throws Exception { new Expectations() {{ mock.call(); result = true; }}; SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { try { assertFalse(mock.call()); } catch (Exception e) { throw new RuntimeException(e); } } }); assertTrue(mock.call()); } }