summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiran Binyamin <liranb@google.com>2024-04-04 22:48:01 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-04-04 22:48:01 +0000
commitd0c9098e3cda5fd6755e5ac089077bfc55b03fa6 (patch)
tree787b954a31dc7882ce69eb6824e294edc8aedd49
parente1e7a35af3cd7d530343c0a2c0bc1ce40edd6508 (diff)
parentdb4edcf60c7b9b2961681d8f44a248ff9117c218 (diff)
downloadmockito-d0c9098e3cda5fd6755e5ac089077bfc55b03fa6.tar.gz
Merge changes from topic "mockito-upgrade-2-23-0" into mainHEADmastermain
* changes: Reapply "Fixed DefaultMockitoSession constructor" Reapply "New API to clean up all inline mocks after test" Upgrade mockito to version 2.23.0
-rw-r--r--README.version6
-rw-r--r--src/main/java/org/mockito/ArgumentCaptor.java4
-rw-r--r--src/main/java/org/mockito/exceptions/misusing/InjectMocksException.java16
-rw-r--r--src/main/java/org/mockito/internal/creation/SuspendMethod.java10
-rw-r--r--src/main/java/org/mockito/internal/creation/settings/CreationSettings.java1
-rw-r--r--src/main/java/org/mockito/internal/exceptions/Reporter.java2
-rw-r--r--src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java2
-rw-r--r--src/main/java/org/mockito/internal/junit/UniversalTestListener.java19
-rw-r--r--src/main/java/org/mockito/internal/listeners/AutoCleanableListener.java17
-rw-r--r--src/main/java/org/mockito/internal/progress/MockingProgressImpl.java23
-rw-r--r--src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java1
-rw-r--r--src/main/java/org/mockito/plugins/InlineMockMaker.java1
-rw-r--r--src/test/java/org/mockito/internal/progress/MockingProgressImplTest.java56
-rw-r--r--src/test/java/org/mockito/internal/session/DefaultMockitoSessionBuilderTest.java10
-rw-r--r--src/test/java/org/mockito/internal/util/MockSettingsTest.java17
-rw-r--r--src/test/java/org/mockitousage/basicapi/MocksCreationTest.java40
-rw-r--r--src/test/java/org/mockitousage/session/MockitoSessionTest.java46
-rw-r--r--src/test/java/org/mockitousage/verification/VerificationInOrderWithTimeoutTest.java207
-rw-r--r--src/test/java/org/mockitousage/verification/VerificationWithAfterTest.java2
-rw-r--r--src/test/java/org/mockitoutil/RetryRule.java56
-rw-r--r--src/test/java/org/mockitoutil/async/AsyncTesting.java4
-rw-r--r--subprojects/inline/src/test/java/org/mockitoinline/bugs/CyclicMockMethodArgumentMemoryLeakTest.java1
-rw-r--r--subprojects/inline/src/test/java/org/mockitoinline/bugs/SelfSpyReferenceMemoryLeakTest.java1
23 files changed, 460 insertions, 82 deletions
diff --git a/README.version b/README.version
index 1a82721..3cce812 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,5 @@ 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)
+ Fixed DefaultMockitoSession constructor. (I14ed7c032a974c3a65caaf091d36d9667ea331b6)
+ New API to clean up all inline mocks after test (8bdfbf053ab6e4fc14a3eaecb613f5838fdf0f09)
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: &#64;{@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/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/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/DefaultMockitoSession.java b/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java
index c81baf2..c3f15f3 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 {
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
index 8771aa7..ddc3ff6 100644
--- a/src/main/java/org/mockito/plugins/InlineMockMaker.java
+++ b/src/main/java/org/mockito/plugins/InlineMockMaker.java
@@ -50,3 +50,4 @@ public interface InlineMockMaker extends MockMaker {
void clearAllMocks();
}
+
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
index 439c888..936bd01 100644
--- a/subprojects/inline/src/test/java/org/mockitoinline/bugs/CyclicMockMethodArgumentMemoryLeakTest.java
+++ b/subprojects/inline/src/test/java/org/mockitoinline/bugs/CyclicMockMethodArgumentMemoryLeakTest.java
@@ -37,3 +37,4 @@ public class CyclicMockMethodArgumentMemoryLeakTest {
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
index f4bb55a..0ef8e71 100644
--- a/subprojects/inline/src/test/java/org/mockitoinline/bugs/SelfSpyReferenceMemoryLeakTest.java
+++ b/subprojects/inline/src/test/java/org/mockitoinline/bugs/SelfSpyReferenceMemoryLeakTest.java
@@ -33,3 +33,4 @@ public class SelfSpyReferenceMemoryLeakTest {
}
}
}
+