diff options
author | Liran Binyamin <liranb@google.com> | 2024-04-03 15:41:23 -0400 |
---|---|---|
committer | Liran Binyamin <liranb@google.com> | 2024-04-03 15:42:50 -0400 |
commit | 70d9b29729996aebf6de5b3d536e379d38e4209c (patch) | |
tree | 9a2c6708b6e6412596dfa9e3a18bcc492bc41116 | |
parent | e1e7a35af3cd7d530343c0a2c0bc1ce40edd6508 (diff) | |
download | mockito-70d9b29729996aebf6de5b3d536e379d38e4209c.tar.gz |
Upgrade mockito to version 2.23.0
This is a clean version of mockito v2.23.0 without any local patches applied.
Bug: 140773999
Test: presubmit
Change-Id: I9c9fb77395921c72f3a402672303b34e7c32dab9
29 files changed, 463 insertions, 414 deletions
diff --git a/README.version b/README.version index 1a82721..fc67c47 100644 --- a/README.version +++ b/README.version @@ -1,5 +1,5 @@ URL: https://github.com/mockito/mockito -Version: v2.21.0 +Version: v2.23.0 License: Apache 2.0 Description: Mockito is a mocking framework with a clean and simple API. @@ -9,5 +9,4 @@ Dexmaker module. The source can be updated using the update_source.sh script. Local Modifications: - Fixed DefaultMockitoSession constructor. (I14ed7c032a974c3a65caaf091d36d9667ea331b6) - New API to clean up all inline mocks after test (8bdfbf053ab6e4fc14a3eaecb613f5838fdf0f09) + None diff --git a/src/main/java/org/mockito/ArgumentCaptor.java b/src/main/java/org/mockito/ArgumentCaptor.java index 1104de9..7011c92 100644 --- a/src/main/java/org/mockito/ArgumentCaptor.java +++ b/src/main/java/org/mockito/ArgumentCaptor.java @@ -49,7 +49,7 @@ import org.mockito.internal.matchers.CapturingMatcher; * Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing. * * <p> - * This utility class <strong>*don't do any type checks*</strong>, the generic signatures are only there to avoid casting + * This utility class <strong>*doesn't do any type checks*</strong>. The generic signatures are only there to avoid casting * in your code. * <p> * There is an <strong>annotation</strong> that you might find useful: @{@link Captor} @@ -136,7 +136,7 @@ public class ArgumentCaptor<T> { /** * Build a new <code>ArgumentCaptor</code>. * <p> - * Note that an <code>ArgumentCaptor</code> <b>*don't do any type checks*</b>, it is only there to avoid casting + * Note that an <code>ArgumentCaptor</code> <b>*doesn't do any type checks*</b>. It is only there to avoid casting * in your code. This might however change (type checks could be added) in a * future major release. * diff --git a/src/main/java/org/mockito/Mockito.java b/src/main/java/org/mockito/Mockito.java index 4058340..2d06e58 100644 --- a/src/main/java/org/mockito/Mockito.java +++ b/src/main/java/org/mockito/Mockito.java @@ -103,8 +103,7 @@ import org.mockito.verification.VerificationWithTimeout; * <a href="#43">43. New API for integrations: <code>MockitoSession</code> is usable by testing frameworks (Since 2.15.+)</a><br/> * <a href="#44">44. Deprecated <code>org.mockito.plugins.InstantiatorProvider</code> as it was leaking internal API. it was replaced by <code>org.mockito.plugins.InstantiatorProvider2 (Since 2.15.4)</code></a><br/> * <a href="#45">45. New JUnit Jupiter (JUnit5+) extension</a><br/> - * <a href="#46">46. New <code>Mockito.lenient()</code> and <code>MockSettings.lenient()</code> methods (Since 2.20.0)</a><br/> - * <a href="#47">47. New API for clearing mock state in inline mocking (Since 2.25.0)</a><br/> + * <a href="#46">46. New <code>Mockito.lenient()</code> and <code>MockSettings.lenient()</code> methods (Since 2.20.0</a><br/> * </b> * * <h3 id="0">0. <a class="meaningful_link" href="#mockito2" name="mockito2">Migrating to Mockito 2</a></h3> @@ -1533,15 +1532,6 @@ import org.mockito.verification.VerificationWithTimeout; * * For more information refer to {@link Mockito#lenient()}. * Let us know how do you find the new feature by opening a GitHub issue to discuss! - * - * <h3 id="47">47. <a class="meaningful_link" href="#clear_inline_mocks" name="clear_inline_mocks">New API for clearing mock state in inline mocking (Since 2.25.0)</a></h3> - * - * In certain specific, rare scenarios (issue <a href="https://github.com/mockito/mockito/pull/1619">#1619</a>) - * inline mocking causes memory leaks. - * There is no clean way to mitigate this problem completely. - * Hence, we introduced a new API to explicitly clear mock state (only make sense in inline mocking!). - * See example usage in {@link MockitoFramework#clearInlineMocks()}. - * If you have feedback or a better idea how to solve the problem please reach out. */ @SuppressWarnings("unchecked") public class Mockito extends ArgumentMatchers { diff --git a/src/main/java/org/mockito/MockitoFramework.java b/src/main/java/org/mockito/MockitoFramework.java index 58cd4b6..5ffe272 100644 --- a/src/main/java/org/mockito/MockitoFramework.java +++ b/src/main/java/org/mockito/MockitoFramework.java @@ -92,55 +92,4 @@ public interface MockitoFramework { */ @Incubating InvocationFactory getInvocationFactory(); - - /** - * Clears up internal state of all inline mocks. - * This method is only meaningful if inline mock maker is in use. - * Otherwise this method is a no-op and need not be used. - * <p> - * This method is useful to tackle subtle memory leaks that are possible due to the nature of inline mocking - * (issue <a href="https://github.com/mockito/mockito/pull/1619">#1619</a>). - * If you are facing those problems, call this method at the end of the test (or in "@After" method). - * See examples of using "clearInlineMocks" in Mockito test code. - * To find out why inline mock maker keeps track of the mock objects see {@link org.mockito.plugins.InlineMockMaker}. - * <p> - * Mockito's "inline mocking" enables mocking final types, enums and final methods - * (read more in section 39 of {@link Mockito} javadoc). - * This method is only meaningful when {@link org.mockito.plugins.InlineMockMaker} is in use. - * If you're using a different {@link org.mockito.plugins.MockMaker} then this method is a no-op. - * - * <pre class="code"><code class="java"> - * public class ExampleTest { - * - * @After - * public void clearMocks() { - * Mockito.framework().clearInlineMocks(); - * } - * - * @Test - * public void someTest() { - * ... - * } - * } - * </pre> - * - * If you have feedback or a better idea how to solve the problem please reach out. - * - * @since 2.25.0 - * @see #clearInlineMock(Object) - */ - @Incubating - void clearInlineMocks(); - - /** - * Clears up internal state of specific inline mock. - * This method is a single-mock variant of {@link #clearInlineMocks()}. - * Please read javadoc for {@link #clearInlineMocks()}. - * - * @param mock to clear up - * @since 2.25.0 - * @see #clearInlineMocks() - */ - @Incubating - void clearInlineMock(Object mock); } diff --git a/src/main/java/org/mockito/exceptions/misusing/InjectMocksException.java b/src/main/java/org/mockito/exceptions/misusing/InjectMocksException.java new file mode 100644 index 0000000..616d4b6 --- /dev/null +++ b/src/main/java/org/mockito/exceptions/misusing/InjectMocksException.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018 Mockito contributors + * This program is made available under the terms of the MIT License. + */ +package org.mockito.exceptions.misusing; + +import org.mockito.exceptions.base.MockitoException; + +/** + * Thrown when creation of test subject annotated with InjectMocks fails. + */ +public class InjectMocksException extends MockitoException { + public InjectMocksException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/mockito/internal/creation/SuspendMethod.java b/src/main/java/org/mockito/internal/creation/SuspendMethod.java index 018bc50..42ceac6 100644 --- a/src/main/java/org/mockito/internal/creation/SuspendMethod.java +++ b/src/main/java/org/mockito/internal/creation/SuspendMethod.java @@ -11,12 +11,18 @@ import java.util.Arrays; * See <a href="https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md#continuation-passing-style">Design docs for details</a>. */ public class SuspendMethod { - private static final String KOTLIN_CONTINUATION = "kotlin.coroutines.experimental.Continuation"; + private static final String KOTLIN_EXPERIMENTAL_CONTINUATION = "kotlin.coroutines.experimental.Continuation"; + private static final String KOTLIN_CONTINUATION = "kotlin.coroutines.Continuation"; public static Class<?>[] trimSuspendParameterTypes(Class<?>[] parameterTypes) { int n = parameterTypes.length; - if (n > 0 && parameterTypes[n - 1].getName().equals(KOTLIN_CONTINUATION)) + if (n > 0 && isContinuationType(parameterTypes[n - 1])) return Arrays.copyOf(parameterTypes, n - 1); return parameterTypes; } + + private static boolean isContinuationType(Class<?> parameterType) { + String name = parameterType.getName(); + return name.equals(KOTLIN_CONTINUATION) || name.equals(KOTLIN_EXPERIMENTAL_CONTINUATION); + } } diff --git a/src/main/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMaker.java b/src/main/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMaker.java index dfe2061..42f10ce 100644 --- a/src/main/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMaker.java +++ b/src/main/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMaker.java @@ -14,7 +14,6 @@ import org.mockito.internal.util.Platform; import org.mockito.internal.util.concurrent.WeakConcurrentMap; import org.mockito.invocation.MockHandler; import org.mockito.mock.MockCreationSettings; -import org.mockito.plugins.InlineMockMaker; import java.io.File; import java.io.FileOutputStream; @@ -88,7 +87,7 @@ import static org.mockito.internal.util.StringUtil.join; * support this feature. */ @Incubating -public class InlineByteBuddyMockMaker implements ClassCreatingMockMaker, InlineMockMaker { +public class InlineByteBuddyMockMaker implements ClassCreatingMockMaker { private static final Instrumentation INSTRUMENTATION; @@ -277,16 +276,6 @@ public class InlineByteBuddyMockMaker implements ClassCreatingMockMaker, InlineM } @Override - public void clearMock(Object mock) { - mocks.remove(mock); - } - - @Override - public void clearAllMocks() { - mocks.clear(); - } - - @Override public TypeMockability isTypeMockable(final Class<?> type) { return new TypeMockability() { @Override diff --git a/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java b/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java index 03afd80..81f52f9 100644 --- a/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java +++ b/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java @@ -57,6 +57,7 @@ public class CreationSettings<T> implements MockCreationSettings<T>, Serializabl this.outerClassInstance = copy.getOuterClassInstance(); this.constructorArgs = copy.getConstructorArgs(); this.lenient = copy.lenient; + this.stripAnnotations = copy.stripAnnotations; } @Override diff --git a/src/main/java/org/mockito/internal/exceptions/Reporter.java b/src/main/java/org/mockito/internal/exceptions/Reporter.java index 2bc4445..38135a0 100644 --- a/src/main/java/org/mockito/internal/exceptions/Reporter.java +++ b/src/main/java/org/mockito/internal/exceptions/Reporter.java @@ -673,7 +673,7 @@ public class Reporter { } public static MockitoException fieldInitialisationThrewException(Field field, Throwable details) { - return new MockitoException(join( + return new InjectMocksException(join( "Cannot instantiate @InjectMocks field named '" + field.getName() + "' of type '" + field.getType() + "'.", "You haven't provided the instance at field declaration so I tried to construct the instance.", "However the constructor or the initialization block threw an exception : " + details.getMessage(), diff --git a/src/main/java/org/mockito/internal/framework/DefaultMockitoFramework.java b/src/main/java/org/mockito/internal/framework/DefaultMockitoFramework.java index d92fc28..69a733c 100644 --- a/src/main/java/org/mockito/internal/framework/DefaultMockitoFramework.java +++ b/src/main/java/org/mockito/internal/framework/DefaultMockitoFramework.java @@ -10,8 +10,6 @@ import org.mockito.internal.invocation.DefaultInvocationFactory; import org.mockito.internal.util.Checks; import org.mockito.invocation.InvocationFactory; import org.mockito.listeners.MockitoListener; -import org.mockito.plugins.InlineMockMaker; -import org.mockito.plugins.MockMaker; import org.mockito.plugins.MockitoPlugins; import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress; @@ -39,25 +37,4 @@ public class DefaultMockitoFramework implements MockitoFramework { public InvocationFactory getInvocationFactory() { return new DefaultInvocationFactory(); } - - private InlineMockMaker getInlineMockMaker() { - MockMaker mockMaker = Plugins.getMockMaker(); - return (mockMaker instanceof InlineMockMaker) ? (InlineMockMaker) mockMaker : null; - } - - @Override - public void clearInlineMocks() { - InlineMockMaker mockMaker = getInlineMockMaker(); - if (mockMaker != null) { - mockMaker.clearAllMocks(); - } - } - - @Override - public void clearInlineMock(Object mock) { - InlineMockMaker mockMaker = getInlineMockMaker(); - if (mockMaker != null) { - mockMaker.clearMock(mock); - } - } } diff --git a/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java b/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java index c81baf2..a472f55 100644 --- a/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java +++ b/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java @@ -18,12 +18,10 @@ import java.util.List; public class DefaultMockitoSession implements MockitoSession { - private final List<Object> testClassInstances; private final String name; private final UniversalTestListener listener; public DefaultMockitoSession(List<Object> testClassInstances, String name, Strictness strictness, MockitoLogger logger) { - this.testClassInstances = testClassInstances; this.name = name; listener = new UniversalTestListener(strictness, logger); try { @@ -36,20 +34,9 @@ public class DefaultMockitoSession implements MockitoSession { for (Object testClassInstance : testClassInstances) { MockitoAnnotations.initMocks(testClassInstance); } - } catch (RuntimeException | Error e) { - try { - // TODO: ideally this scenario should be tested on DefaultMockitoSessionBuilderTest, - // but we don't have any Android.bp project to run it. - // Besides, the latest Mockito code (https://github.com/mockito/mockito/blob/main/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java - // at the time this patch was merged) has a different workflow, where the listener - // is marked as dirty when an exception is thrown, so we're forking the solution. - Mockito.framework().removeListener(listener); - } catch (RuntimeException | Error e2) { - // Ignore it, as the real failure is e, thrown at the end - System.err.println("DefaultMockitoSession: ignoring exception thrown when removing " - + "listener " + listener); - e2.printStackTrace(System.err); - } + } catch (RuntimeException e) { + //clean up in case 'initMocks' fails + listener.setListenerDirty(); throw e; } } diff --git a/src/main/java/org/mockito/internal/junit/UniversalTestListener.java b/src/main/java/org/mockito/internal/junit/UniversalTestListener.java index 66c9dee..f670c64 100644 --- a/src/main/java/org/mockito/internal/junit/UniversalTestListener.java +++ b/src/main/java/org/mockito/internal/junit/UniversalTestListener.java @@ -5,6 +5,7 @@ package org.mockito.internal.junit; import org.mockito.internal.creation.settings.CreationSettings; +import org.mockito.internal.listeners.AutoCleanableListener; import org.mockito.internal.util.MockitoLogger; import org.mockito.mock.MockCreationSettings; import org.mockito.quality.Strictness; @@ -18,13 +19,14 @@ import java.util.Map; * Will come handy when we offer tweaking strictness at the method level with annotation. * Should be relatively easy to improve and offer tweaking strictness per mock. */ -public class UniversalTestListener implements MockitoTestListener { +public class UniversalTestListener implements MockitoTestListener, AutoCleanableListener { private Strictness currentStrictness; private final MockitoLogger logger; private Map<Object, MockCreationSettings> mocks = new IdentityHashMap<Object, MockCreationSettings>(); private DefaultStubbingLookupListener stubbingLookupListener; + private boolean listenerDirty; public UniversalTestListener(Strictness initialStrictness, MockitoLogger logger) { this.currentStrictness = initialStrictness; @@ -85,4 +87,19 @@ public class UniversalTestListener implements MockitoTestListener { this.currentStrictness = strictness; this.stubbingLookupListener.setCurrentStrictness(strictness); } + + /** + * See {@link AutoCleanableListener#isListenerDirty()} + */ + @Override + public boolean isListenerDirty() { + return listenerDirty; + } + + /** + * Marks listener as dirty, scheduled for cleanup when the next session starts + */ + public void setListenerDirty() { + this.listenerDirty = true; + } } diff --git a/src/main/java/org/mockito/internal/listeners/AutoCleanableListener.java b/src/main/java/org/mockito/internal/listeners/AutoCleanableListener.java new file mode 100644 index 0000000..cfd2a53 --- /dev/null +++ b/src/main/java/org/mockito/internal/listeners/AutoCleanableListener.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018 Mockito contributors + * This program is made available under the terms of the MIT License. + */ +package org.mockito.internal.listeners; + +/** + * Listener that is automatically cleaned up (removed from the the global list of subscribers). + * For now, we don't intend to make this interface public. + */ +public interface AutoCleanableListener { + + /** + * Indicates that the listener is dirty and should be removed from the subscribers + */ + boolean isListenerDirty(); +} diff --git a/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java b/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java index 2685ddf..5c4fbbc 100644 --- a/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java +++ b/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java @@ -9,6 +9,7 @@ import org.mockito.internal.configuration.GlobalConfiguration; import org.mockito.internal.debugging.Localized; import org.mockito.internal.debugging.LocationImpl; import org.mockito.internal.exceptions.Reporter; +import org.mockito.internal.listeners.AutoCleanableListener; import org.mockito.invocation.Location; import org.mockito.listeners.MockCreationListener; import org.mockito.listeners.MockitoListener; @@ -19,6 +20,8 @@ import org.mockito.verification.VerificationMode; import org.mockito.verification.VerificationStrategy; import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import static org.mockito.internal.exceptions.Reporter.unfinishedStubbing; @@ -154,12 +157,28 @@ public class MockingProgressImpl implements MockingProgress { } public void addListener(MockitoListener listener) { + addListener(listener, listeners); + } + + static void addListener(MockitoListener listener, Set<MockitoListener> listeners) { + List<MockitoListener> delete = new LinkedList<MockitoListener>(); for (MockitoListener existing : listeners) { if (existing.getClass().equals(listener.getClass())) { - Reporter.redundantMockitoListener(listener.getClass().getSimpleName()); + if (existing instanceof AutoCleanableListener && ((AutoCleanableListener) existing).isListenerDirty()) { + //dirty listener means that there was an exception even before the test started + //if we fail here with redundant mockito listener exception there will be multiple failures causing confusion + //so we simply remove the existing listener and move on + delete.add(existing); + } else { + Reporter.redundantMockitoListener(listener.getClass().getSimpleName()); + } } } - this.listeners.add(listener); + //delete dirty listeners so they don't occupy state/memory and don't receive notifications + for (MockitoListener toDelete : delete) { + listeners.remove(toDelete); + } + listeners.add(listener); } public void removeListener(MockitoListener listener) { diff --git a/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java b/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java index eded985..840efb7 100644 --- a/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java +++ b/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java @@ -47,6 +47,7 @@ public class VerificationWrapperInOrderWrapper implements VerificationMode { } } + //TODO ugly exception message!!! throw new MockitoException(verificationMode.getClass().getSimpleName() + " is not implemented to work with InOrder wrapped inside a " + verificationWrapper.getClass().getSimpleName()); diff --git a/src/main/java/org/mockito/plugins/InlineMockMaker.java b/src/main/java/org/mockito/plugins/InlineMockMaker.java deleted file mode 100644 index 8771aa7..0000000 --- a/src/main/java/org/mockito/plugins/InlineMockMaker.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 Mockito contributors - * This program is made available under the terms of the MIT License. - */ - -package org.mockito.plugins; - -import org.mockito.Incubating; -import org.mockito.MockitoFramework; - -/** - * Extension to {@link MockMaker} for mock makers that changes inline method implementations - * and need keep track of created mock objects. - * <p> - * Mockito's default inline mock maker keeps track of created mock objects via weak reference map. - * This poses a risk of memory leaks in certain scenarios - * (issue <a href="https://github.com/mockito/mockito/pull/1619">#1619</a>). - * There is no clean way to tackle those problems at the moment. - * Hence, {@code InlineMockMaker} interface exposes methods to explicitly clear mock references. - * Those methods are called by {@link MockitoFramework#clearInlineMocks()}. - * When the user encounters a leak, he can mitigate the problem with {@link MockitoFramework#clearInlineMocks()}. - * <p> - * {@code InlineMockMaker} is for expert users and framework integrators, when custom inline mock maker is in use. - * If you have a custom {@link MockMaker} that keeps track of mock objects, - * please have your mock maker implement {@code InlineMockMaker} interface. - * This way, it can participate in {@link MockitoFramework#clearInlineMocks()} API. - * - * @since 2.25.0 - */ -@Incubating -public interface InlineMockMaker extends MockMaker { - - /** - * Clean up internal state for specified {@code mock}. You may assume there won't be any interaction to the specific - * mock after this is called. - * - * @param mock the mock instance whose internal state is to be cleaned. - * @since 2.25.0 - */ - @Incubating - void clearMock(Object mock); - - /** - * Cleans up internal state for all existing mocks. You may assume there won't be any interaction to mocks created - * previously after this is called. - * - * @since 2.25.0 - */ - @Incubating - void clearAllMocks(); - -} diff --git a/src/test/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMakerTest.java b/src/test/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMakerTest.java index 3613b5f..51c321d 100644 --- a/src/test/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMakerTest.java +++ b/src/test/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMakerTest.java @@ -20,11 +20,7 @@ import org.mockito.mock.MockCreationSettings; import org.mockito.mock.SerializableMode; import org.mockito.plugins.MockMaker; -import java.util.HashMap; -import java.util.List; -import java.util.Observable; -import java.util.Observer; -import java.util.Set; +import java.util.*; import java.util.regex.Pattern; import static net.bytebuddy.ClassFileVersion.JAVA_V8; @@ -291,37 +287,6 @@ public class InlineByteBuddyMockMakerTest extends AbstractByteBuddyMockMakerTest .getOnly().getParameters().getOnly().getName()).isEqualTo("bar"); } - @Test - public void test_clear_mock_clears_handler() { - MockCreationSettings<GenericSubClass> settings = settingsFor(GenericSubClass.class); - GenericSubClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<GenericSubClass>(settings)); - assertThat(mockMaker.getHandler(proxy)).isNotNull(); - - //when - mockMaker.clearMock(proxy); - - //then - assertThat(mockMaker.getHandler(proxy)).isNull(); - } - - @Test - public void test_clear_all_mock_clears_handler() { - MockCreationSettings<GenericSubClass> settings = settingsFor(GenericSubClass.class); - GenericSubClass proxy1 = mockMaker.createMock(settings, new MockHandlerImpl<GenericSubClass>(settings)); - assertThat(mockMaker.getHandler(proxy1)).isNotNull(); - - settings = settingsFor(GenericSubClass.class); - GenericSubClass proxy2 = mockMaker.createMock(settings, new MockHandlerImpl<GenericSubClass>(settings)); - assertThat(mockMaker.getHandler(proxy1)).isNotNull(); - - //when - mockMaker.clearAllMocks(); - - //then - assertThat(mockMaker.getHandler(proxy1)).isNull(); - assertThat(mockMaker.getHandler(proxy2)).isNull(); - } - private static <T> MockCreationSettings<T> settingsFor(Class<T> type, Class<?>... extraInterfaces) { MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>(); mockSettings.setTypeToMock(type); diff --git a/src/test/java/org/mockito/internal/framework/DefaultMockitoFrameworkTest.java b/src/test/java/org/mockito/internal/framework/DefaultMockitoFrameworkTest.java index ae21488..0937b69 100644 --- a/src/test/java/org/mockito/internal/framework/DefaultMockitoFrameworkTest.java +++ b/src/test/java/org/mockito/internal/framework/DefaultMockitoFrameworkTest.java @@ -10,26 +10,15 @@ import org.mockito.ArgumentMatchers; import org.mockito.MockSettings; import org.mockito.StateMaster; import org.mockito.exceptions.misusing.RedundantListenerException; -import org.mockito.internal.configuration.plugins.Plugins; import org.mockito.listeners.MockCreationListener; import org.mockito.listeners.MockitoListener; import org.mockito.mock.MockCreationSettings; -import org.mockito.plugins.InlineMockMaker; import org.mockitoutil.TestBase; import java.util.List; import java.util.Set; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockingDetails; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.withSettings; +import static org.mockito.Mockito.*; import static org.mockitoutil.ThrowableAssert.assertThat; public class DefaultMockitoFrameworkTest extends TestBase { @@ -123,52 +112,5 @@ public class DefaultMockitoFrameworkTest extends TestBase { "For more information, see the javadoc for RedundantListenerException class."); } - @Test - public void clearing_all_mocks_is_safe_regardless_of_mock_maker_type() { - List mock = mock(List.class); - - //expect - assertTrue(mockingDetails(mock).isMock()); - framework.clearInlineMocks(); - } - - @Test - public void clears_all_mocks() { - //clearing mocks only works with inline mocking - assumeTrue(Plugins.getMockMaker() instanceof InlineMockMaker); - - //given - List list1 = mock(List.class); - assertTrue(mockingDetails(list1).isMock()); - List list2 = mock(List.class); - assertTrue(mockingDetails(list2).isMock()); - - //when - framework.clearInlineMocks(); - - //then - assertFalse(mockingDetails(list1).isMock()); - assertFalse(mockingDetails(list2).isMock()); - } - - @Test - public void clears_mock() { - //clearing mocks only works with inline mocking - assumeTrue(Plugins.getMockMaker() instanceof InlineMockMaker); - - //given - List list1 = mock(List.class); - assertTrue(mockingDetails(list1).isMock()); - List list2 = mock(List.class); - assertTrue(mockingDetails(list2).isMock()); - - //when - framework.clearInlineMock(list1); - - //then - assertFalse(mockingDetails(list1).isMock()); - assertTrue(mockingDetails(list2).isMock()); - } - private static class MyListener implements MockitoListener {} } diff --git a/src/test/java/org/mockito/internal/progress/MockingProgressImplTest.java b/src/test/java/org/mockito/internal/progress/MockingProgressImplTest.java index 40ad320..7ef0334 100644 --- a/src/test/java/org/mockito/internal/progress/MockingProgressImplTest.java +++ b/src/test/java/org/mockito/internal/progress/MockingProgressImplTest.java @@ -5,14 +5,26 @@ package org.mockito.internal.progress; +import org.assertj.core.api.Assertions; +import org.assertj.core.api.ThrowableAssert; import org.junit.Before; import org.junit.Test; import org.mockito.exceptions.base.MockitoException; +import org.mockito.exceptions.misusing.RedundantListenerException; +import org.mockito.internal.listeners.AutoCleanableListener; import org.mockito.internal.verification.VerificationModeFactory; +import org.mockito.listeners.MockitoListener; import org.mockito.verification.VerificationMode; import org.mockitoutil.TestBase; -import static org.junit.Assert.*; +import java.util.LinkedHashSet; +import java.util.Set; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class MockingProgressImplTest extends TestBase { @@ -53,4 +65,46 @@ public class MockingProgressImplTest extends TestBase { //then no exception is thrown: mockingProgress.mockingStarted(null, null); } + + @Test + public void should_not_allow_redundant_listeners() { + MockitoListener listener1 = mock(MockitoListener.class); + final MockitoListener listener2 = mock(MockitoListener.class); + + final Set<MockitoListener> listeners = new LinkedHashSet<MockitoListener>(); + + //when + MockingProgressImpl.addListener(listener1, listeners); + + //then + Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + public void call() { + MockingProgressImpl.addListener(listener2, listeners); + } + }).isInstanceOf(RedundantListenerException.class); + } + + @Test + public void should_clean_up_listeners_automatically() { + MockitoListener someListener = mock(MockitoListener.class); + MyListener cleanListener = mock(MyListener.class); + MyListener dirtyListener = when(mock(MyListener.class).isListenerDirty()).thenReturn(true).getMock(); + + Set<MockitoListener> listeners = new LinkedHashSet<MockitoListener>(); + + //when + MockingProgressImpl.addListener(someListener, listeners); + MockingProgressImpl.addListener(dirtyListener, listeners); + + //then + Assertions.assertThat(listeners).containsExactlyInAnyOrder(someListener, dirtyListener); + + //when + MockingProgressImpl.addListener(cleanListener, listeners); + + //then dirty listener was removed automatically + Assertions.assertThat(listeners).containsExactlyInAnyOrder(someListener, cleanListener); + } + + interface MyListener extends MockitoListener, AutoCleanableListener {} } diff --git a/src/test/java/org/mockito/internal/session/DefaultMockitoSessionBuilderTest.java b/src/test/java/org/mockito/internal/session/DefaultMockitoSessionBuilderTest.java index 855afb0..a65ae21 100644 --- a/src/test/java/org/mockito/internal/session/DefaultMockitoSessionBuilderTest.java +++ b/src/test/java/org/mockito/internal/session/DefaultMockitoSessionBuilderTest.java @@ -97,6 +97,16 @@ public class DefaultMockitoSessionBuilderTest { }).throwsException(UnfinishedMockingSessionException.class); } + @Test public void auto_cleans_dirty_listeners() { + new DefaultMockitoSessionBuilder().startMocking(); + + ThrowableAssert.assertThat(new Runnable() { + public void run() { + new DefaultMockitoSessionBuilder().startMocking(); + } + }).throwsException(UnfinishedMockingSessionException.class); + } + class TestClass { @Mock public Set<Object> set; diff --git a/src/test/java/org/mockito/internal/util/MockSettingsTest.java b/src/test/java/org/mockito/internal/util/MockSettingsTest.java index 76219c2..01df499 100644 --- a/src/test/java/org/mockito/internal/util/MockSettingsTest.java +++ b/src/test/java/org/mockito/internal/util/MockSettingsTest.java @@ -6,15 +6,16 @@ package org.mockito.internal.util; import org.junit.Test; import org.mockito.Mockito; +import org.mockito.internal.creation.settings.CreationSettings; import org.mockito.mock.MockCreationSettings; import org.mockitoutil.TestBase; import java.util.List; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class MockSettingsTest extends TestBase { - @Test public void public_api_for_creating_settings() throws Exception { //when @@ -26,4 +27,18 @@ public class MockSettingsTest extends TestBase { assertEquals(List.class, settings.getTypeToMock()); assertEquals("dummy", settings.getMockName().toString()); } + @Test + public void test_without_annotations() throws Exception { + MockCreationSettings<List> settings = Mockito.withSettings() + .withoutAnnotations() + .build(List.class); + + CreationSettings copy = new CreationSettings((CreationSettings)settings); + + assertEquals(List.class, settings.getTypeToMock()); + assertEquals(List.class, copy.getTypeToMock()); + + assertTrue(settings.isStripAnnotations()); + assertTrue(copy.isStripAnnotations()); + } } diff --git a/src/test/java/org/mockitousage/basicapi/MocksCreationTest.java b/src/test/java/org/mockitousage/basicapi/MocksCreationTest.java index 98ab7d2..b5892ef 100644 --- a/src/test/java/org/mockitousage/basicapi/MocksCreationTest.java +++ b/src/test/java/org/mockitousage/basicapi/MocksCreationTest.java @@ -12,13 +12,21 @@ import org.mockito.exceptions.verification.SmartNullPointerException; import org.mockitousage.IMethods; import org.mockitoutil.TestBase; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.LinkedList; import java.util.List; import java.util.Set; -import static org.junit.Assert.*; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.RETURNS_SMART_NULLS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; @SuppressWarnings("unchecked") public class MocksCreationTest extends TestBase { @@ -26,12 +34,12 @@ public class MocksCreationTest extends TestBase { private class HasPrivateConstructor {} @Test - public void shouldCreateMockWhenConstructorIsPrivate() { + public void should_create_mock_when_constructor_is_private() { assertNotNull(Mockito.mock(HasPrivateConstructor.class)); } @Test - public void shouldCombineMockNameAndSmartNulls() { + public void should_combine_mock_name_and_smart_nulls() { //given IMethods mock = mock(IMethods.class, withSettings() .defaultAnswer(RETURNS_SMART_NULLS) @@ -51,7 +59,7 @@ public class MocksCreationTest extends TestBase { } @Test - public void shouldCombineMockNameAndExtraInterfaces() { + public void should_combine_mock_name_and_extra_interfaces() { //given IMethods mock = mock(IMethods.class, withSettings() .extraInterfaces(List.class) @@ -67,7 +75,7 @@ public class MocksCreationTest extends TestBase { } @Test - public void shouldSpecifyMockNameViaSettings() { + public void should_specify_mock_name_via_settings() { //given IMethods mock = mock(IMethods.class, withSettings().name("great mockie")); @@ -79,7 +87,7 @@ public class MocksCreationTest extends TestBase { } @Test - public void shouldScreamWhenSpyCreatedWithWrongType() { + public void should_scream_when_spy_created_with_wrong_type() { //given List list = new LinkedList(); try { @@ -92,14 +100,28 @@ public class MocksCreationTest extends TestBase { @SuppressWarnings({"CheckReturnValue", "MockitoUsage"}) @Test - public void shouldAllowCreatingSpiesWithCorrectType() { + public void should_allow_creating_spies_with_correct_type() { List list = new LinkedList(); mock(LinkedList.class, withSettings().spiedInstance(list)); } @Test - public void shouldAllowInlineMockCreation() throws Exception { + public void should_allow_inline_mock_creation() { when(mock(Set.class).isEmpty()).thenReturn(false); } + @Retention(RetentionPolicy.RUNTIME) + @interface SomeAnnotation {} + + @SomeAnnotation static class Foo {} + + @Test + public void should_strip_annotations() { + Foo withAnnotations = mock(Foo.class); + Foo withoutAnnotations = mock(Foo.class, withSettings().withoutAnnotations()); + + //expect: + assertTrue(withAnnotations.getClass().isAnnotationPresent(SomeAnnotation.class)); + assertFalse(withoutAnnotations.getClass().isAnnotationPresent(SomeAnnotation.class)); + } } diff --git a/src/test/java/org/mockitousage/session/MockitoSessionTest.java b/src/test/java/org/mockitousage/session/MockitoSessionTest.java index a87928c..5271f92 100644 --- a/src/test/java/org/mockitousage/session/MockitoSessionTest.java +++ b/src/test/java/org/mockitousage/session/MockitoSessionTest.java @@ -5,12 +5,15 @@ package org.mockitousage.session; import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.JUnitCore; import org.junit.runner.Result; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoSession; +import org.mockito.exceptions.misusing.InjectMocksException; import org.mockito.exceptions.misusing.UnfinishedStubbingException; import org.mockito.quality.Strictness; import org.mockitousage.IMethods; @@ -97,6 +100,17 @@ public class MockitoSessionTest extends TestBase { resetState(); } + @Test public void cleans_up_state_when_init_fails() { + //when + Result result = junit.run(MockitoSessionTest.SessionWithInitMocksFailure.class); + + //expect that both failures are the same, indicating correct listener cleanup + //incorrect cleanup causes 1 failure to be InjectMocksException + // but the next test method would have failed with unuseful error that session was not cleaned up + JUnitResultAssert.assertThat(result) + .fails(2, InjectMocksException.class); + } + public static class SessionWithoutAnyConfiguration { @Mock IMethods mock; @@ -221,4 +235,36 @@ public class MockitoSessionTest extends TestBase { verify(mock); } } + + public static class SessionWithInitMocksFailure { + @InjectMocks private ConstructorFail sut; + MockitoSession mockito; + + @Before + public void before() { + mockito = Mockito.mockitoSession().initMocks(this).startMocking(); + } + + @After public void after() { + if (mockito != null) { + //so that we reduce amount of exceptions for easier assertions + //otherwise we would get an NPE here + mockito.finishMocking(); + } + } + + @Test public void test1() { + //should fail the same way + } + + @Test public void test2() { + //should fail the same way + } + + static class ConstructorFail { + ConstructorFail() { + throw new RuntimeException("Boo!"); + } + } + } } diff --git a/src/test/java/org/mockitousage/verification/VerificationInOrderWithTimeoutTest.java b/src/test/java/org/mockitousage/verification/VerificationInOrderWithTimeoutTest.java new file mode 100644 index 0000000..5e1bdcb --- /dev/null +++ b/src/test/java/org/mockitousage/verification/VerificationInOrderWithTimeoutTest.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2007 Mockito contributors + * This program is made available under the terms of the MIT License. + */ + +package org.mockitousage.verification; + +import org.assertj.core.api.Assertions; +import org.assertj.core.api.ThrowableAssert; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.exceptions.base.MockitoException; +import org.mockito.exceptions.verification.VerificationInOrderFailure; +import org.mockito.junit.MockitoRule; +import org.mockitousage.IMethods; +import org.mockitoutil.async.AsyncTesting; + +import static org.mockito.Mockito.after; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.timeout; +import static org.mockito.junit.MockitoJUnit.rule; + +public class VerificationInOrderWithTimeoutTest { + + @Rule public MockitoRule mockito = rule(); + + @Mock private IMethods mock1; + @Mock private IMethods mock2; + + private AsyncTesting async; + + @Before public void setUp() { + async = new AsyncTesting(); + } + + @After public void tearDown() { + async.cleanUp(); + } + + @Test + public void should_not_allow_in_order_with_after() { + // expect + Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + public void call() { + inOrder(mock1).verify(mock1, after(100)).oneArg('a'); + } + }).isInstanceOf(MockitoException.class).hasMessageContaining("not implemented to work with InOrder"); + //TODO specific exception + } + + @Test + public void should_verify_in_order_with_timeout() { + // when + async.runAfter(20, callMock(mock1, 'a')); + async.runAfter(50, callMock(mock1, 'c')); + async.runAfter(200, callMock(mock2, 'b')); + + // then + InOrder inOrder = inOrder(mock1, mock2); + inOrder.verify(mock1, timeout(100)).oneArg('a'); + inOrder.verify(mock2, timeout(500)).oneArg('b'); + } + + @Test + public void should_verify_in_order_with_timeout_and_fail() { + // when + async.runAfter(20, callMock(mock1, 'a')); + async.runAfter(100, callMock(mock2, 'b')); + + // then + final InOrder inOrder = inOrder(mock1, mock2); + inOrder.verify(mock2, timeout(300)).oneArg('b'); + Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + public void call() { + inOrder.verify(mock1, timeout(300)).oneArg('a'); + } + }).isInstanceOf(VerificationInOrderFailure.class) + .hasMessageContaining("Wanted but not invoked:\nmock1.oneArg('a');") + .hasMessageContaining("Wanted anywhere AFTER following interaction:\nmock2.oneArg('b');"); + } + + @Test + public void should_verify_in_order_with_times_x() { + // when + async.runAfter(20, callMock(mock1, 'a')); + async.runAfter(50, callMock(mock1, 'a')); + async.runAfter(200, callMock(mock2, 'b')); + async.runAfter(250, callMock(mock2, 'b')); + + // then + InOrder inOrder = inOrder(mock1, mock2); + inOrder.verify(mock1, timeout(100).times(2)).oneArg('a'); + inOrder.verify(mock2, timeout(500).times(2)).oneArg('b'); + } + + @Test + public void should_verify_in_order_with_times_x_and_fail() { + // when + async.runAfter(20, callMock(mock1, 'a')); + async.runAfter(50, callMock(mock1, 'a')); + async.runAfter(200, callMock(mock2, 'b')); + async.runAfter(250, callMock(mock2, 'b')); + + // then + final InOrder inOrder = inOrder(mock1, mock2); + inOrder.verify(mock2, timeout(500).times(2)).oneArg('b'); + + Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + public void call() { + inOrder.verify(mock1, timeout(100).times(2)).oneArg('a'); + } + }).isInstanceOf(VerificationInOrderFailure.class) + .hasMessageContaining("Wanted but not invoked:\nmock1.oneArg('a');") + .hasMessageContaining("Wanted anywhere AFTER following interaction:\nmock2.oneArg('b');"); + } + + @Test + public void should_not_allow_in_order_with_only() { + Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + @Override + public void call() throws Throwable { + inOrder(mock1).verify(mock1, timeout(200).only()).oneArg('a'); + } + }).isInstanceOf(MockitoException.class).hasMessageContaining("not implemented to work with InOrder"); + //TODO specific exception + } + + @Test + public void should_verify_in_order_with_at_least_once() { + // when + async.runAfter(20, callMock(mock1, 'a')); + async.runAfter(50, callMock(mock1, 'a')); + async.runAfter(100, callMock(mock2, 'b')); + async.runAfter(120, callMock(mock2, 'b')); + + // then + InOrder inOrder = inOrder(mock1, mock2); + inOrder.verify(mock1, timeout(200).atLeastOnce()).oneArg('a'); + inOrder.verify(mock2, timeout(500).atLeastOnce()).oneArg('b'); + } + + @Test + public void should_verify_in_order_with_at_least_once_and_fail() { + // when + async.runAfter(20, callMock(mock1, 'a')); + async.runAfter(50, callMock(mock1, 'a')); + async.runAfter(100, callMock(mock2, 'b')); + async.runAfter(120, callMock(mock2, 'b')); + + // then + final InOrder inOrder = inOrder(mock1, mock2); + inOrder.verify(mock2, timeout(300).atLeastOnce()).oneArg('b'); + Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + public void call() { + inOrder.verify(mock1, timeout(500).atLeastOnce()).oneArg('a'); + } + }).isInstanceOf(VerificationInOrderFailure.class) + .hasMessageContaining("Wanted but not invoked:\nmock1.oneArg('a');") + .hasMessageContaining("Wanted anywhere AFTER following interaction:\nmock2.oneArg('b');"); + } + + @Test + public void should_verify_in_order_with_at_least_x() { + // when + async.runAfter(20, callMock(mock1, 'a')); + async.runAfter(50, callMock(mock1, 'a')); + async.runAfter(100, callMock(mock2, 'b')); + async.runAfter(120, callMock(mock2, 'b')); + + // then + InOrder inOrder = inOrder(mock1, mock2); + inOrder.verify(mock1, timeout(200).atLeast(2)).oneArg('a'); + inOrder.verify(mock2, timeout(500).atLeast(2)).oneArg('b'); + } + + @Test + public void should_verify_in_order_with_at_least_x_and_fail() { + // when + async.runAfter(20, callMock(mock1, 'a')); + async.runAfter(50, callMock(mock1, 'a')); + async.runAfter(100, callMock(mock2, 'b')); + async.runAfter(120, callMock(mock2, 'b')); + + // then + final InOrder inOrder = inOrder(mock1, mock2); + inOrder.verify(mock2, timeout(300).atLeast(2)).oneArg('b'); + Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + public void call() { + inOrder.verify(mock1, timeout(500).atLeast(2)).oneArg('a'); + } + }).isInstanceOf(AssertionError.class) + .hasMessageContaining("Verification in order failure"); + } + + private Runnable callMock(final IMethods mock, final char c) { + return new Runnable() { + @Override + public void run() { + mock.oneArg(c); + } + }; + } +} diff --git a/src/test/java/org/mockitousage/verification/VerificationWithAfterTest.java b/src/test/java/org/mockitousage/verification/VerificationWithAfterTest.java index f437c03..7bbb52b 100644 --- a/src/test/java/org/mockitousage/verification/VerificationWithAfterTest.java +++ b/src/test/java/org/mockitousage/verification/VerificationWithAfterTest.java @@ -66,7 +66,7 @@ public class VerificationWithAfterTest { Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { @Override public void call() { - verify(mock, after(300)).oneArg('1'); + verify(mock, after(600)).oneArg('1'); } }).isInstanceOf(TooManyActualInvocations.class); } diff --git a/src/test/java/org/mockitoutil/RetryRule.java b/src/test/java/org/mockitoutil/RetryRule.java deleted file mode 100644 index 386ce78..0000000 --- a/src/test/java/org/mockitoutil/RetryRule.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007 Mockito contributors - * This program is made available under the terms of the MIT License. - */ - -package org.mockitoutil; - -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import static java.lang.String.format; - -public class RetryRule implements TestRule { - private final TestRule innerRule; - - public static RetryRule attempts(final int attempts) { - return new RetryRule(new NumberedAttempts(attempts)); - } - - private RetryRule(TestRule innerRule) { - this.innerRule = innerRule; - } - - public Statement apply(final Statement base, final Description description) { - return innerRule.apply(base, description); - } - - private static class NumberedAttempts implements TestRule { - private final int attempts; - - NumberedAttempts(int attempts) { - assert attempts > 1; - this.attempts = attempts; - } - - @Override - public Statement apply(final Statement base, final Description description) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - for (int remainingAttempts = attempts; remainingAttempts > 0 ; remainingAttempts--) { - try { - base.evaluate(); - } catch (Throwable throwable) { - if (remainingAttempts < 0) { - throw new AssertionError(format("Tried this test + %d times and failed", attempts)) - .initCause(throwable); - } - } - } - } - }; - } - } -} diff --git a/src/test/java/org/mockitoutil/async/AsyncTesting.java b/src/test/java/org/mockitoutil/async/AsyncTesting.java index 3b11e10..a193eb6 100644 --- a/src/test/java/org/mockitoutil/async/AsyncTesting.java +++ b/src/test/java/org/mockitoutil/async/AsyncTesting.java @@ -10,11 +10,13 @@ import java.util.LinkedList; * Streamlines testing async code for Mockito tests. * * Instances of this class are NOT thread safe (intentionally, they are not required to be thread safe) + * + * //TODO convert to test rule */ public class AsyncTesting { //Sanity limit of threas. Increase it if justified. - private final static int MAX_THREADS = 3; + private final static int MAX_THREADS = 4; private final LinkedList<Exception> problems = new LinkedList<Exception>(); private final LinkedList<Thread> threads = new LinkedList<Thread>(); diff --git a/subprojects/inline/src/test/java/org/mockitoinline/bugs/CyclicMockMethodArgumentMemoryLeakTest.java b/subprojects/inline/src/test/java/org/mockitoinline/bugs/CyclicMockMethodArgumentMemoryLeakTest.java deleted file mode 100644 index 439c888..0000000 --- a/subprojects/inline/src/test/java/org/mockitoinline/bugs/CyclicMockMethodArgumentMemoryLeakTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Mockito contributors - * This program is made available under the terms of the MIT License. - */ - -package org.mockitoinline.bugs; - -import org.junit.Test; - -import static org.mockito.Mockito.framework; -import static org.mockito.Mockito.mock; - -public class CyclicMockMethodArgumentMemoryLeakTest { - private static final int ARRAY_LENGTH = 1 << 20; // 4 MB - - @Test - public void no_memory_leak_when_cyclically_calling_method_with_mocks() { - for (int i = 0; i < 100; ++i) { - final A a = mock(A.class); - a.largeArray = new int[ARRAY_LENGTH]; - final B b = mock(B.class); - - a.accept(b); - b.accept(a); - - framework().clearInlineMocks(); - } - } - - private static class A { - private int[] largeArray; - - void accept(B b) {} - } - - private static class B { - void accept(A a) {} - } -} diff --git a/subprojects/inline/src/test/java/org/mockitoinline/bugs/SelfSpyReferenceMemoryLeakTest.java b/subprojects/inline/src/test/java/org/mockitoinline/bugs/SelfSpyReferenceMemoryLeakTest.java deleted file mode 100644 index f4bb55a..0000000 --- a/subprojects/inline/src/test/java/org/mockitoinline/bugs/SelfSpyReferenceMemoryLeakTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Mockito contributors - * This program is made available under the terms of the MIT License. - */ - -package org.mockitoinline.bugs; - -import org.junit.Test; - -import static org.mockito.Mockito.framework; -import static org.mockito.Mockito.spy; - -public class SelfSpyReferenceMemoryLeakTest { - private static final int ARRAY_LENGTH = 1 << 20; // 4 MB - - @Test - public void no_memory_leak_when_spy_holds_reference_to_self() { - for (int i = 0; i < 100; ++i) { - final DeepRefSelfClass instance = spy(new DeepRefSelfClass()); - instance.refInstance(instance); - - framework().clearInlineMocks(); - } - } - - private static class DeepRefSelfClass { - private final DeepRefSelfClass[] array = new DeepRefSelfClass[1]; - - private final int[] largeArray = new int[ARRAY_LENGTH]; - - private void refInstance(DeepRefSelfClass instance) { - array[0] = instance; - } - } -} |