Fetch Mockito source code as of commit 691253dbb5
Change-Id: I34169d1cd116e9687cba074a60e80e41eaf3f4c9
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e0840a4
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Mockito contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/src/org/mockito/AdditionalAnswers.java b/src/org/mockito/AdditionalAnswers.java
new file mode 100644
index 0000000..f576f40
--- /dev/null
+++ b/src/org/mockito/AdditionalAnswers.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
+import org.mockito.internal.stubbing.answers.ReturnsElementsOf;
+import org.mockito.internal.stubbing.defaultanswers.ForwardsInvocations;
+import org.mockito.stubbing.Answer;
+
+import java.util.Collection;
+
+/**
+ * Additional answers provides factory methods for less common answers.
+ *
+ * <p>Currently offer answers that can return the parameter of an invocation at a certain position.
+ *
+ * <p>See factory methods for more information : {@link #returnsFirstArg}, {@link #returnsSecondArg},
+ * {@link #returnsLastArg} and {@link #returnsArgAt}
+ *
+ * @since 1.9.5
+ */
+@SuppressWarnings("unchecked")
+public class AdditionalAnswers {
+ private static final ReturnsArgumentAt RETURNS_FIRST_ARGUMENT = new ReturnsArgumentAt(0);
+ private static final ReturnsArgumentAt RETURNS_SECOND_ARGUMENT = new ReturnsArgumentAt(1);
+ private static final ReturnsArgumentAt RETURNS_LAST_ARGUMENT = new ReturnsArgumentAt(-1);
+
+ /**
+ * Returns the first parameter of an invocation.
+ *
+ * <p>
+ * This additional answer could be used at stub time using the
+ * <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+ * </p>
+ *
+ * <pre class="code"><code class="java">given(carKeyFob.authenticate(carKey)).will(returnsFirstArg());
+ * doAnswer(returnsFirstArg()).when(carKeyFob).authenticate(carKey)</code></pre>
+ *
+ * @param <T> Return type of the invocation.
+ * @return Answer that will return the first argument of the invocation.
+ *
+ * @since 1.9.5
+ */
+ public static <T> Answer<T> returnsFirstArg() {
+ return (Answer<T>) RETURNS_FIRST_ARGUMENT;
+ }
+
+ /**
+ * Returns the second parameter of an invocation.
+ *
+ * <p>
+ * This additional answer could be used at stub time using the
+ * <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+ * </p>
+ *
+ * <pre class="code"><code class="java">given(trader.apply(leesFormula, onCreditDefaultSwap)).will(returnsSecondArg());
+ * doAnswer(returnsSecondArg()).when(trader).apply(leesFormula, onCreditDefaultSwap)</code></pre>
+ *
+ * @param <T> Return type of the invocation.
+ * @return Answer that will return the second argument of the invocation.
+ *
+ * @since 1.9.5
+ */
+ public static <T> Answer<T> returnsSecondArg() {
+ return (Answer<T>) RETURNS_SECOND_ARGUMENT;
+ }
+
+ /**
+ * Returns the last parameter of an invocation.
+ *
+ * <p>
+ * This additional answer could be used at stub time using the
+ * <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+ * </p>
+ *
+ * <pre class="code"><code class="java">given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
+ * doAnswer(returnsLastArg()).when(person).remember(dream1, dream2, dream3, dream4)</code></pre>
+ *
+ * @param <T> Return type of the invocation.
+ * @return Answer that will return the last argument of the invocation.
+ *
+ * @since 1.9.5
+ */
+ public static <T> Answer<T> returnsLastArg() {
+ return (Answer<T>) RETURNS_LAST_ARGUMENT;
+ }
+
+ /**
+ * Returns the parameter of an invocation at the given position.
+ *
+ * <p>
+ * This additional answer could be used at stub time using the
+ * <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+ * </p>
+ *
+ * <pre class="code"><code class="java">given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(3));
+ * doAnswer(returnsArgAt(3)).when(person).remember(dream1, dream2, dream3, dream4)</code></pre>
+ *
+ * @param <T> Return type of the invocation.
+ * @return Answer that will return the second argument of the invocation.
+ *
+ * @since 1.9.5
+ */
+ public static <T> Answer<T> returnsArgAt(int position) {
+ return (Answer<T>) new ReturnsArgumentAt(position);
+ }
+
+ /**
+ * An answer that directly forwards the calls to the delegate.
+ * <p>
+ * Useful for spies or partial mocks of objects that are difficult to mock
+ * or spy using the usual spy API. Possible use cases:
+ * <ul>
+ * <li>Final classes but with an interface</li>
+ * <li>Already custom proxied object</li>
+ * <li>Special objects with a finalize method, i.e. to avoid executing it 2 times</li>
+ * </ul>
+ * For more details including the use cases reported by users take a look at
+ * <a link="http://code.google.com/p/mockito/issues/detail?id=145">issue 145</a>.
+ * <p>
+ * The difference with the regular spy:
+ * <ul>
+ * <li>
+ * The regular spy ({@link Mockito#spy(Object)}) contains <strong>all</strong> state from the spied instance
+ * and the methods are invoked on the spy. The spied instance is only used at mock creation to copy the state from.
+ * If you call a method on a regular spy and it internally calls other methods on this spy, those calls are remembered
+ * for verifications, and they can be effectively stubbed.
+ * </li>
+ * <li>
+ * The mock that delegates simply delegates all methods to the delegate.
+ * The delegate is used all the time as methods are delegated onto it.
+ * If you call a method on a mock that delegates and it internally calls other methods on this mock,
+ * those calls are <strong>not</strong> remembered for verifications, stubbing does not have effect on them, too.
+ * Mock that delegates is less powerful than the regular spy but it is useful when the regular spy cannot be created.
+ * </li>
+ * </ul>
+ * An example with a final class that we want to delegate to:
+ * <p>
+ * <pre class="code"><code class="java">
+ * final class DontYouDareToMockMe implements list { ... }
+ *
+ * DontYouDareToMockMe awesomeList = new DontYouDareToMockMe();
+ *
+ * List mock = mock(List.class, delegatesTo(awesomeList));
+ * </code></pre>
+ *
+ * <p>
+ * This feature suffers from the same drawback as the spy.
+ * The mock will call the delegate if you use regular when().then() stubbing style.
+ * Since the real implementation is called this might have some side effects.
+ * Therefore you should to use the doReturn|Throw|Answer|CallRealMethod stubbing style. Example:
+ *
+ * <pre class="code"><code class="java">
+ * List listWithDelegate = mock(List.class, AdditionalAnswers.delegatesTo(awesomeList));
+ *
+ * //Impossible: real method is called so listWithDelegate.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ * when(listWithDelegate.get(0)).thenReturn("foo");
+ *
+ * //You have to use doReturn() for stubbing
+ * doReturn("foo").when(listWithDelegate).get(0);
+ * </code></pre>
+ *
+ * @param delegate The delegate to forward calls to.
+ * @return the answer
+ *
+ * @since 1.9.5
+ */
+ public static <T> Answer<T> delegatesTo(Object delegate) {
+ return (Answer<T>) new ForwardsInvocations(delegate);
+ }
+
+ /**
+ * Returns elements of the collection. Keeps returning the last element forever.
+ * Might be useful on occasion when you have a collection of elements to return.
+ * <p>
+ * <pre class="code"><code class="java">
+ * //this:
+ * when(mock.foo()).thenReturn(1, 2, 3);
+ *
+ * //is equivalent to:
+ * when(mock.foo()).thenAnswer(new ReturnsElementsOf(Arrays.asList(1, 2, 3)));
+ * </code></pre>
+ *
+ * @param elements The collection of elements to return.
+ * @return the answer
+ *
+ * @since 1.9.5
+ */
+ public static <T> Answer<T> returnsElementsOf(Collection<?> elements) {
+ return (Answer<T>) new ReturnsElementsOf(elements);
+ }
+}
diff --git a/src/org/mockito/AdditionalMatchers.java b/src/org/mockito/AdditionalMatchers.java
new file mode 100644
index 0000000..c0a297f
--- /dev/null
+++ b/src/org/mockito/AdditionalMatchers.java
@@ -0,0 +1,992 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito;
+
+import org.mockito.internal.matchers.ArrayEquals;
+import org.mockito.internal.matchers.CompareEqual;
+import org.mockito.internal.matchers.EqualsWithDelta;
+import org.mockito.internal.matchers.Find;
+import org.mockito.internal.matchers.GreaterOrEqual;
+import org.mockito.internal.matchers.GreaterThan;
+import org.mockito.internal.matchers.LessOrEqual;
+import org.mockito.internal.matchers.LessThan;
+import org.mockito.internal.progress.HandyReturnValues;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+
+/**
+ * See {@link Matchers} for general info about matchers.
+ * <p>
+ * AdditionalMatchers provides rarely used matchers, kept only for somewhat compatibility with EasyMock.
+ * Use additional matchers very judiciously because they may impact readability of a test.
+ * It is recommended to use matchers from {@link Matchers} and keep stubbing and verification simple.
+ * <p>
+ * Example of using logical and(), not(), or() matchers:
+ *
+ * <pre class="code"><code class="java">
+ * //anything but not "ejb"
+ * mock.someMethod(not(eq("ejb")));
+ *
+ * //not "ejb" and not "michael jackson"
+ * mock.someMethod(and(not(eq("ejb")), not(eq("michael jackson"))));
+ *
+ * //1 or 10
+ * mock.someMethod(or(eq(1), eq(10)));
+ * </code></pre>
+ *
+ * Scroll down to see all methods - full list of matchers.
+ */
+public class AdditionalMatchers {
+
+ private static MockingProgress mockingProgress = new ThreadSafeMockingProgress();
+
+ /**
+ * argument greater than or equal the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>null</code>.
+ */
+ public static <T extends Comparable<T>> T geq(Comparable<T> value) {
+ return reportMatcher(new GreaterOrEqual<T>(value)).<T>returnNull();
+ }
+
+ /**
+ * byte argument greater than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static byte geq(byte value) {
+ return reportMatcher(new GreaterOrEqual<Byte>(value)).returnZero();
+ }
+
+ /**
+ * double argument greater than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static double geq(double value) {
+ return reportMatcher(new GreaterOrEqual<Double>(value)).returnZero();
+ }
+
+ /**
+ * float argument greater than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static float geq(float value) {
+ return reportMatcher(new GreaterOrEqual<Float>(value)).returnZero();
+ }
+
+ /**
+ * int argument greater than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static int geq(int value) {
+ return reportMatcher(new GreaterOrEqual<Integer>(value)).returnZero();
+ }
+
+ /**
+ * long argument greater than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static long geq(long value) {
+ return reportMatcher(new GreaterOrEqual<Long>(value)).returnZero();
+ }
+
+ /**
+ * short argument greater than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static short geq(short value) {
+ return reportMatcher(new GreaterOrEqual<Short>(value)).returnZero();
+ }
+
+ /**
+ * comparable argument less than or equal the given value details.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>null</code>.
+ */
+ public static <T extends Comparable<T>> T leq(Comparable<T> value) {
+ return reportMatcher(new LessOrEqual<T>(value)).<T>returnNull();
+ }
+
+ /**
+ * byte argument less than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static byte leq(byte value) {
+ return reportMatcher(new LessOrEqual<Byte>(value)).returnZero();
+ }
+
+ /**
+ * double argument less than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static double leq(double value) {
+ return reportMatcher(new LessOrEqual<Double>(value)).returnZero();
+ }
+
+ /**
+ * float argument less than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static float leq(float value) {
+ return reportMatcher(new LessOrEqual<Float>(value)).returnZero();
+ }
+
+ /**
+ * int argument less than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static int leq(int value) {
+ return reportMatcher(new LessOrEqual<Integer>(value)).returnZero();
+ }
+
+ /**
+ * long argument less than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static long leq(long value) {
+ return reportMatcher(new LessOrEqual<Long>(value)).returnZero();
+ }
+
+ /**
+ * short argument less than or equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static short leq(short value) {
+ return reportMatcher(new LessOrEqual<Short>(value)).returnZero();
+ }
+
+ /**
+ * comparable argument greater than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>null</code>.
+ */
+ public static <T extends Comparable<T>> T gt(Comparable<T> value) {
+ return reportMatcher(new GreaterThan<T>(value)).<T>returnNull();
+ }
+
+ /**
+ * byte argument greater than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static byte gt(byte value) {
+ return reportMatcher(new GreaterThan<Byte>(value)).returnZero();
+ }
+
+ /**
+ * double argument greater than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static double gt(double value) {
+ return reportMatcher(new GreaterThan<Double>(value)).returnZero();
+ }
+
+ /**
+ * float argument greater than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static float gt(float value) {
+ return reportMatcher(new GreaterThan<Float>(value)).returnZero();
+ }
+
+ /**
+ * int argument greater than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static int gt(int value) {
+ return reportMatcher(new GreaterThan<Integer>(value)).returnZero();
+ }
+
+ /**
+ * long argument greater than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static long gt(long value) {
+ return reportMatcher(new GreaterThan<Long>(value)).returnZero();
+ }
+
+ /**
+ * short argument greater than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static short gt(short value) {
+ return reportMatcher(new GreaterThan<Short>(value)).returnZero();
+ }
+
+ /**
+ * comparable argument less than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>null</code>.
+ */
+ public static <T extends Comparable<T>> T lt(Comparable<T> value) {
+ return reportMatcher(new LessThan<T>(value)).<T>returnNull();
+ }
+
+ /**
+ * byte argument less than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static byte lt(byte value) {
+ return reportMatcher(new LessThan<Byte>(value)).returnZero();
+ }
+
+ /**
+ * double argument less than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static double lt(double value) {
+ return reportMatcher(new LessThan<Double>(value)).returnZero();
+ }
+
+ /**
+ * float argument less than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static float lt(float value) {
+ return reportMatcher(new LessThan<Float>(value)).returnZero();
+ }
+
+ /**
+ * int argument less than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static int lt(int value) {
+ return reportMatcher(new LessThan<Integer>(value)).returnZero();
+ }
+
+ /**
+ * long argument less than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static long lt(long value) {
+ return reportMatcher(new LessThan<Long>(value)).returnZero();
+ }
+
+ /**
+ * short argument less than the given value.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static short lt(short value) {
+ return reportMatcher(new LessThan<Short>(value)).returnZero();
+ }
+
+ /**
+ * comparable argument equals to the given value according to their
+ * compareTo method.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>null</code>.
+ */
+ public static <T extends Comparable<T>> T cmpEq(Comparable<T> value) {
+ return reportMatcher(new CompareEqual<T>(value)).<T>returnNull();
+ }
+
+ /**
+ * String argument that contains a substring that matches the given regular
+ * expression.
+ *
+ * @param regex
+ * the regular expression.
+ * @return <code>null</code>.
+ */
+ public static String find(String regex) {
+ return reportMatcher(new Find(regex)).<String>returnNull();
+ }
+
+ /**
+ * Object array argument that is equal to the given array, i.e. it has to
+ * have the same type, length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param <T>
+ * the type of the array, it is passed through to prevent casts.
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static <T> T[] aryEq(T[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * short array argument that is equal to the given array, i.e. it has to
+ * have the same length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static short[] aryEq(short[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * long array argument that is equal to the given array, i.e. it has to have
+ * the same length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static long[] aryEq(long[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * int array argument that is equal to the given array, i.e. it has to have
+ * the same length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static int[] aryEq(int[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * float array argument that is equal to the given array, i.e. it has to
+ * have the same length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static float[] aryEq(float[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * double array argument that is equal to the given array, i.e. it has to
+ * have the same length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static double[] aryEq(double[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * char array argument that is equal to the given array, i.e. it has to have
+ * the same length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static char[] aryEq(char[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * byte array argument that is equal to the given array, i.e. it has to have
+ * the same length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static byte[] aryEq(byte[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * boolean array argument that is equal to the given array, i.e. it has to
+ * have the same length, and each element has to be equal.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given array.
+ * @return <code>null</code>.
+ */
+ public static boolean[] aryEq(boolean[] value) {
+ return reportMatcher(new ArrayEquals(value)).returnNull();
+ }
+
+ /**
+ * boolean argument that matches both given matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>false</code>.
+ */
+ public static boolean and(boolean first, boolean second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().returnFalse();
+ }
+
+ /**
+ * byte argument that matches both given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static byte and(byte first, byte second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().returnZero();
+ }
+
+ /**
+ * char argument that matches both given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static char and(char first, char second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().returnChar();
+ }
+
+ /**
+ * double argument that matches both given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static double and(double first, double second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().returnZero();
+ }
+
+ /**
+ * float argument that matches both given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static float and(float first, float second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().returnZero();
+ }
+
+ /**
+ * int argument that matches both given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static int and(int first, int second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().returnZero();
+ }
+
+ /**
+ * long argument that matches both given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static long and(long first, long second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().returnZero();
+ }
+
+ /**
+ * short argument that matches both given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static short and(short first, short second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().returnZero();
+ }
+
+ /**
+ * Object argument that matches both given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param <T>
+ * the type of the object, it is passed through to prevent casts.
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>null</code>.
+ */
+ public static <T> T and(T first, T second) {
+ return mockingProgress.getArgumentMatcherStorage().reportAnd().<T>returnNull();
+ }
+
+ /**
+ * boolean argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>false</code>.
+ */
+ public static boolean or(boolean first, boolean second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().returnFalse();
+ }
+
+ /**
+ * Object argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param <T>
+ * the type of the object, it is passed through to prevent casts.
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>null</code>.
+ */
+ public static <T> T or(T first, T second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().<T>returnNull();
+ }
+
+ /**
+ * short argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static short or(short first, short second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().returnZero();
+ }
+
+ /**
+ * long argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static long or(long first, long second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().returnZero();
+ }
+
+ /**
+ * int argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static int or(int first, int second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().returnZero();
+ }
+
+ /**
+ * float argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static float or(float first, float second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().returnZero();
+ }
+
+ /**
+ * double argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static double or(double first, double second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().returnZero();
+ }
+
+ /**
+ * char argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static char or(char first, char second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().returnChar();
+ }
+
+ /**
+ * byte argument that matches any of the given argument matchers.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the first argument matcher.
+ * @param second
+ * placeholder for the second argument matcher.
+ * @return <code>0</code>.
+ */
+ public static byte or(byte first, byte second) {
+ return mockingProgress.getArgumentMatcherStorage().reportOr().returnZero();
+ }
+
+ /**
+ * Object argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param <T>
+ * the type of the object, it is passed through to prevent casts.
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>null</code>.
+ */
+ public static <T> T not(T first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().<T>returnNull();
+ }
+
+ /**
+ * short argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>0</code>.
+ */
+ public static short not(short first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().returnZero();
+ }
+
+ /**
+ * int argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>0</code>.
+ */
+ public static int not(int first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().returnZero();
+ }
+
+ /**
+ * long argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>0</code>.
+ */
+ public static long not(long first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().returnZero();
+ }
+
+ /**
+ * float argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>0</code>.
+ */
+ public static float not(float first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().returnZero();
+ }
+
+ /**
+ * double argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>0</code>.
+ */
+ public static double not(double first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().returnZero();
+ }
+
+ /**
+ * char argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>0</code>.
+ */
+ public static char not(char first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().returnChar();
+ }
+
+ /**
+ * boolean argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>false</code>.
+ */
+ public static boolean not(boolean first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().returnFalse();
+ }
+
+ /**
+ * byte argument that does not match the given argument matcher.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param first
+ * placeholder for the argument matcher.
+ * @return <code>0</code>.
+ */
+ public static byte not(byte first) {
+ return mockingProgress.getArgumentMatcherStorage().reportNot().returnZero();
+ }
+
+ /**
+ * double argument that has an absolute difference to the given value that
+ * is less than the given delta details.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @param delta
+ * the given delta.
+ * @return <code>0</code>.
+ */
+ public static double eq(double value, double delta) {
+ return reportMatcher(new EqualsWithDelta(value, delta)).returnZero();
+ }
+
+ /**
+ * float argument that has an absolute difference to the given value that is
+ * less than the given delta details.
+ * <p>
+ * See examples in javadoc for {@link AdditionalMatchers} class
+ *
+ * @param value
+ * the given value.
+ * @param delta
+ * the given delta.
+ * @return <code>0</code>.
+ */
+ public static float eq(float value, float delta) {
+ return reportMatcher(new EqualsWithDelta(value, delta)).returnZero();
+ }
+
+ private static HandyReturnValues reportMatcher(ArgumentMatcher<?> matcher) {
+ return mockingProgress.getArgumentMatcherStorage().reportMatcher(matcher);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/Answers.java b/src/org/mockito/Answers.java
new file mode 100644
index 0000000..7da30d1
--- /dev/null
+++ b/src/org/mockito/Answers.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.internal.stubbing.defaultanswers.GloballyConfiguredAnswer;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsMocks;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsSmartNulls;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Enumeration of pre-configured mock answers
+ * <p>
+ * You can use it to pass extra parameters to @Mock annotation, see more info here: {@link Mock}
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * @Mock(answer = RETURNS_DEEP_STUBS) UserProvider userProvider;
+ * </code></pre>
+ * <b>This is not the full list</b> of Answers available in Mockito. Some interesting answers can be found in org.mockito.stubbing.answers package.
+ */
+public enum Answers {
+
+ /**
+ * The default configured answer of every mock.
+ *
+ * <p>Please see the {@link org.mockito.Mockito#RETURNS_DEFAULTS} documentation for more details.</p>
+ *
+ * @see org.mockito.Mockito#RETURNS_DEFAULTS
+ */
+ RETURNS_DEFAULTS(new GloballyConfiguredAnswer()),
+
+ /**
+ * An answer that returns smart-nulls.
+ *
+ * <p>Please see the {@link org.mockito.Mockito#RETURNS_SMART_NULLS} documentation for more details.</p>
+ *
+ * @see org.mockito.Mockito#RETURNS_SMART_NULLS
+ */
+ RETURNS_SMART_NULLS(new ReturnsSmartNulls()),
+
+ /**
+ * An answer that returns <strong>mocks</strong> (not stubs).
+ *
+ * <p>Please see the {@link org.mockito.Mockito#RETURNS_MOCKS} documentation for more details.</p>
+ *
+ * @see org.mockito.Mockito#RETURNS_MOCKS
+ */
+ RETURNS_MOCKS(new ReturnsMocks()),
+
+
+ /**
+ * An answer that returns <strong>deep stubs</strong> (not mocks).
+ *
+ * <p>Please see the {@link org.mockito.Mockito#RETURNS_DEEP_STUBS} documentation for more details.</p>
+ *
+ * @see org.mockito.Mockito#RETURNS_DEEP_STUBS
+ */
+ RETURNS_DEEP_STUBS(new ReturnsDeepStubs()),
+
+ /**
+ * An answer that calls the real methods (used for partial mocks).
+ *
+ * <p>Please see the {@link org.mockito.Mockito#CALLS_REAL_METHODS} documentation for more details.</p>
+ *
+ * @see org.mockito.Mockito#CALLS_REAL_METHODS
+ */
+ CALLS_REAL_METHODS(new CallsRealMethods())
+ ;
+
+ private Answer<Object> implementation;
+
+ private Answers(Answer<Object> implementation) {
+ this.implementation = implementation;
+ }
+
+ public Answer<Object> get() {
+ return implementation;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/ArgumentCaptor.java b/src/org/mockito/ArgumentCaptor.java
new file mode 100644
index 0000000..808e441
--- /dev/null
+++ b/src/org/mockito/ArgumentCaptor.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.internal.matchers.CapturingMatcher;
+import org.mockito.internal.matchers.VarargCapturingMatcher;
+import org.mockito.internal.progress.HandyReturnValues;
+
+import java.util.List;
+
+/**
+ * Use it to capture argument values for further assertions.
+ *
+ * <p>
+ * Mockito verifies argument values in natural java style: by using an equals() method.
+ * This is also the recommended way of matching arguments because it makes tests clean & simple.
+ * In some situations though, it is helpful to assert on certain arguments after the actual verification.
+ * For example:
+ * <pre class="code"><code class="java">
+ * ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+ * verify(mock).doSomething(argument.capture());
+ * assertEquals("John", argument.getValue().getName());
+ * </code></pre>
+ *
+ * <p>
+ * <strong>Warning:</strong> it is recommended to use ArgumentCaptor with verification <strong>but not</strong> with stubbing.
+ * Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.
+ * Also it may reduce defect localization because if stubbed method was not called then no argument is captured.
+ *
+ * <p>
+ * In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).
+ * Both techniques can be used for making sure certain arguments where passed to mocks.
+ * However, ArgumentCaptor may be a better fit if:
+ * <ul>
+ * <li>custom argument matcher is not likely to be reused</li>
+ * <li>you just need it to assert on argument values to complete verification</li>
+ * </ul>
+ * 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
+ * in your code. If you want specific types, then you should do that the captured values.
+ * This behavior might change (type checks could be added) in a
+ * future major release.
+ * <p>
+ * There is an <strong>annotation</strong> that you might find useful: @{@link Captor}
+ * <p>
+ * See the full documentation on Mockito in javadoc for {@link Mockito} class.
+ *
+ * @see Captor
+ * @since 1.8.0
+ */
+public class ArgumentCaptor<T> {
+
+ HandyReturnValues handyReturnValues = new HandyReturnValues();
+
+ private final CapturingMatcher<T> capturingMatcher = new CapturingMatcher<T>();
+ private final VarargCapturingMatcher<T> varargCapturingMatcher = new VarargCapturingMatcher<T>();
+ private final Class<T> clazz;
+
+ /**
+ * @deprecated
+ *
+ * <b>Please use factory method {@link ArgumentCaptor#forClass(Class)} to create captors</b>
+ * <p>
+ * This is required to avoid NullPointerExceptions when autoUnboxing primitive types.
+ * See issue 99.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+ * verify(mock).doSomething(argument.capture());
+ * assertEquals("John", argument.getValue().getName());
+ * </code></pre>
+ */
+ @Deprecated
+ public ArgumentCaptor() {
+ this.clazz = null;
+ }
+
+ ArgumentCaptor(Class<T> clazz) {
+ this.clazz = clazz;
+ }
+
+ /**
+ * Use it to capture the argument. This method <b>must be used inside of verification</b>.
+ * <p>
+ * Internally, this method registers a special implementation of an {@link ArgumentMatcher}.
+ * This argument matcher stores the argument value so that you can use it later to perform assertions.
+ * <p>
+ * See examples in javadoc for {@link ArgumentCaptor} class.
+ *
+ * @return null or default values
+ */
+ public T capture() {
+ Mockito.argThat(capturingMatcher);
+ return handyReturnValues.returnFor(clazz);
+ }
+
+ /**
+ * Use it to capture the variable arguments. This method <b>must be used inside of verification</b>.
+ * <p>
+ * Internally, this method registers a special implementation of an {@link ArgumentMatcher}.
+ * This argument matcher stores the variable arguments values so that you can use it later to perform assertions.
+ * <p>
+ * See examples in javadoc for {@link ArgumentCaptor} class.
+ *
+ * @return null or default values
+ */
+ public T captureVararg() {
+ Mockito.argThat(varargCapturingMatcher);
+ return handyReturnValues.returnFor(clazz);
+ }
+
+
+ /**
+ * Returns the captured value of the argument.
+ * <p>
+ * If the method was called multiple times then it returns the latest captured value.
+ * <p>
+ * See examples in javadoc for {@link ArgumentCaptor} class.
+ *
+ * @return captured argument value
+ */
+ public T getValue() {
+ return this.capturingMatcher.getLastValue();
+ }
+
+ /**
+ * Returns the captured value of the variable arguments.
+ * <p>
+ * If the method was called multiple times then it returns the latest captured variable arguments.
+ * <p>
+ * See examples in javadoc for {@link ArgumentCaptor} class.
+ *
+ * @return captured varargs
+ */
+ public List<T> getVarargsValues() {
+ return this.varargCapturingMatcher.getLastVarargs();
+ }
+
+ /**
+ * Returns all captured values. Use it in case the verified method was called multiple times.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * ArgumentCaptor<Person> peopleCaptor = ArgumentCaptor.forClass(Person.class);
+ * verify(mock, times(2)).doSomething(peopleCaptor.capture());
+ *
+ * List<Person> capturedPeople = peopleCaptor.getAllValues();
+ * assertEquals("John", capturedPeople.get(0).getName());
+ * assertEquals("Jane", capturedPeople.get(1).getName());
+ * </code></pre>
+ * See more examples in javadoc for {@link ArgumentCaptor} class.
+ *
+ * @return captured argument value
+ */
+ public List<T> getAllValues() {
+ return this.capturingMatcher.getAllValues();
+ }
+
+ /**
+ * Returns all captured variable arguments. Use it in case the verified method was called multiple times.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * ArgumentCaptor<Person> peopleFornamesCaptor = ArgumentCaptor.forClass(String.class);
+ * verify(mock, times(2)).doSomething(peopleFornamesCaptor.captureVarargs());
+ *
+ * List<String> peopleFornames = peopleFornamesCaptor.getAllVarargs();
+ * assertThat(peopleFornames.get(0)).contains("John", "Carl");
+ * assertThat(peopleFornames.get(1)).contains("Janes", "Eloise", "Lois");
+ * </code></pre>
+ * See more examples in javadoc for {@link ArgumentCaptor} class.
+ *
+ * @return all captured varargs
+ */
+ public List<List<T>> getAllVarargsValues() {
+ return this.varargCapturingMatcher.getAllVarargs();
+ }
+
+ /**
+ * 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
+ * in your code. This might however change (type checks could be added) in a
+ * future major release.
+ *
+ * @param clazz Type matching the parameter to be captured.
+ * @param <T> Type of clazz
+ * @return A new ArgumentCaptor
+ */
+ public static <T> ArgumentCaptor<T> forClass(Class<T> clazz) {
+ return new ArgumentCaptor<T>(clazz);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/ArgumentMatcher.java b/src/org/mockito/ArgumentMatcher.java
new file mode 100644
index 0000000..bfa441d
--- /dev/null
+++ b/src/org/mockito/ArgumentMatcher.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.mockito.internal.util.Decamelizer;
+
+/**
+ * Allows creating customized argument matchers.
+ * <p>
+ * ArgumentMatcher is an hamcrest {@link Matcher} with predefined describeTo() method.
+ * In case of failure, ArgumentMatcher generates description based on <b>decamelized class name</b> - to promote meaningful class names.
+ * For example <b>StringWithStrongLanguage</b> matcher will generate 'String with strong language' description.
+ * You can always override describeTo() method and provide detailed description.
+ * <p>
+ * Use {@link Matchers#argThat} method and pass an instance of hamcrest {@link Matcher}, e.g:
+ *
+ * <pre class="code"><code class="java">
+ * class IsListOfTwoElements extends ArgumentMatcher<List> {
+ * public boolean matches(Object list) {
+ * return ((List) list).size() == 2;
+ * }
+ * }
+ *
+ * List mock = mock(List.class);
+ *
+ * when(mock.addAll(argThat(new IsListOfTwoElements()))).thenReturn(true);
+ *
+ * mock.addAll(Arrays.asList("one", "two"));
+ *
+ * verify(mock).addAll(argThat(new IsListOfTwoElements()));
+ * </code></pre>
+ *
+ * To keep it readable you may want to extract method, e.g:
+ *
+ * <pre class="code"><code class="java">
+ * verify(mock).addAll(<b>argThat(new IsListOfTwoElements())</b>);
+ * //becomes
+ * verify(mock).addAll(<b>listOfTwoElements()</b>);
+ * </code></pre>
+ *
+ * <b>Warning:</b> Be reasonable with using complicated argument matching, especially custom argument matchers, as it can make the test less readable.
+ * Sometimes it's better to implement equals() for arguments that are passed to mocks
+ * (Mockito naturally uses equals() for argument matching).
+ * This can make the test cleaner.
+ * <p>
+ * Also, <b>sometimes {@link ArgumentCaptor} may be a better fit</b> than custom matcher.
+ * For example, if custom argument matcher is not likely to be reused
+ * or you just need it to assert on argument values to complete verification of behavior.
+ * <p>
+ * Read more about other matchers in javadoc for {@link Matchers} class
+ *
+ * @param <T> type of argument
+ */
+public abstract class ArgumentMatcher<T> extends BaseMatcher<T> {
+
+ private static final long serialVersionUID = -2145234737829370369L;
+
+ /**
+ * Returns whether this matcher accepts the given argument.
+ * <p>
+ * The method should <b>never</b> assert if the argument doesn't match. It
+ * should only return false.
+ *
+ * @param argument
+ * the argument
+ * @return whether this matcher accepts the given argument.
+ */
+ public abstract boolean matches(Object argument);
+
+ /**
+ * By default this method decamelizes matchers name to promote meaningful names for matchers.
+ * <p>
+ * For example <b>StringWithStrongLanguage</b> matcher will generate 'String with strong language' description in case of failure.
+ * <p>
+ * You might want to override this method to
+ * provide more specific description of the matcher (useful when
+ * verification failures are reported).
+ *
+ * @param description the description to which the matcher description is
+ * appended.
+ */
+ public void describeTo(Description description) {
+ String className = getClass().getSimpleName();
+ description.appendText(Decamelizer.decamelizeMatcher(className));
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/BDDMockito.java b/src/org/mockito/BDDMockito.java
new file mode 100644
index 0000000..ec05bb7
--- /dev/null
+++ b/src/org/mockito/BDDMockito.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+import org.mockito.stubbing.Stubber;
+
+/**
+ * Behavior Driven Development style of writing tests uses <b>//given //when //then</b> comments as fundamental parts of your test methods.
+ * This is exactly how we write our tests and we warmly encourage you to do so!
+ * <p>
+ * Start learning about BDD here: <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">http://en.wikipedia.org/wiki/Behavior_Driven_Development</a>
+ * <p>
+ * The problem is that current stubbing api with canonical role of <b>when</b> word does not integrate nicely with <b>//given //when //then</b> comments.
+ * It's because stubbing belongs to <b>given</b> component of the test and not to the <b>when</b> component of the test.
+ * Hence {@link BDDMockito} class introduces an alias so that you stub method calls with {@link BDDMockito#given(Object)} method.
+ * Now it really nicely integrates with the <b>given</b> component of a BDD style test!
+ * <p>
+ * Here is how the test might look like:
+ * <pre class="code"><code class="java">
+ * import static org.mockito.BDDMockito.*;
+ *
+ * Seller seller = mock(Seller.class);
+ * Shop shop = new Shop(seller);
+ *
+ * public void shouldBuyBread() throws Exception {
+ * //given
+ * given(seller.askForBread()).willReturn(new Bread());
+ *
+ * //when
+ * Goods goods = shop.buyBread();
+ *
+ * //then
+ * assertThat(goods, containBread());
+ * }
+ * </code></pre>
+ *
+ * Stubbing voids with throwables:
+ * <pre class="code"><code class="java">
+ * //given
+ * willThrow(new RuntimeException("boo")).given(mock).foo();
+ *
+ * //when
+ * Result result = systemUnderTest.perform();
+ *
+ * //then
+ * assertEquals(failure, result);
+ * </code></pre>
+ * <p>
+ * One of the purposes of BDDMockito is also to show how to tailor the mocking syntax to a different programming style.
+ *
+ * @since 1.8.0
+ */
+@SuppressWarnings("unchecked")
+public class BDDMockito extends Mockito {
+
+ /**
+ * See original {@link OngoingStubbing}
+ * @since 1.8.0
+ */
+ public static interface BDDMyOngoingStubbing<T> {
+
+ /**
+ * See original {@link OngoingStubbing#thenAnswer(Answer)}
+ * @since 1.8.0
+ */
+ BDDMyOngoingStubbing<T> willAnswer(Answer<?> answer);
+
+ /**
+ * See original {@link OngoingStubbing#then(Answer)}
+ * @since 1.9.0
+ */
+ BDDMyOngoingStubbing<T> will(Answer<?> answer);
+
+ /**
+ * See original {@link OngoingStubbing#thenReturn(Object)}
+ * @since 1.8.0
+ */
+ BDDMyOngoingStubbing<T> willReturn(T value);
+
+ /**
+ * See original {@link OngoingStubbing#thenReturn(Object, Object[])}
+ * @since 1.8.0
+ */
+ BDDMyOngoingStubbing<T> willReturn(T value, T... values);
+
+ /**
+ * See original {@link OngoingStubbing#thenThrow(Throwable...)}
+ * @since 1.8.0
+ */
+ BDDMyOngoingStubbing<T> willThrow(Throwable... throwables);
+
+ /**
+ * See original {@link OngoingStubbing#thenThrow(Class[])}
+ * @since 1.9.0
+ */
+ BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable>... throwableClasses);
+
+ /**
+ * See original {@link OngoingStubbing#thenCallRealMethod()}
+ * @since 1.9.0
+ */
+ BDDMyOngoingStubbing<T> willCallRealMethod();
+
+ /**
+ * See original {@link OngoingStubbing#getMock()}
+ * @since 1.9.0
+ */
+ <M> M getMock();
+ }
+
+ public static class BDDOngoingStubbingImpl<T> implements BDDMyOngoingStubbing<T> {
+
+ private final OngoingStubbing<T> mockitoOngoingStubbing;
+
+ public BDDOngoingStubbingImpl(OngoingStubbing<T> ongoingStubbing) {
+ this.mockitoOngoingStubbing = ongoingStubbing;
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDMyOngoingStubbing#willAnswer(Answer)
+ */
+ public BDDMyOngoingStubbing<T> willAnswer(Answer<?> answer) {
+ return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenAnswer(answer));
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDMyOngoingStubbing#will(Answer)
+ */
+ public BDDMyOngoingStubbing<T> will(Answer<?> answer) {
+ return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.then(answer));
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDMyOngoingStubbing#willReturn(java.lang.Object)
+ */
+ public BDDMyOngoingStubbing<T> willReturn(T value) {
+ return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenReturn(value));
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDMyOngoingStubbing#willReturn(java.lang.Object, T[])
+ */
+ public BDDMyOngoingStubbing<T> willReturn(T value, T... values) {
+ return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenReturn(value, values));
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDMyOngoingStubbing#willThrow(java.lang.Throwable[])
+ */
+ public BDDMyOngoingStubbing<T> willThrow(Throwable... throwables) {
+ return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwables));
+ }
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDMyOngoingStubbing#willThrow(java.lang.Class[])
+ */
+ public BDDMyOngoingStubbing<T> willThrow(Class<? extends Throwable>... throwableClasses) {
+ return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenThrow(throwableClasses));
+ }
+
+ public BDDMyOngoingStubbing<T> willCallRealMethod() {
+ return new BDDOngoingStubbingImpl<T>(mockitoOngoingStubbing.thenCallRealMethod());
+ }
+
+ public <M> M getMock() {
+ return (M) mockitoOngoingStubbing.getMock();
+ }
+ }
+
+ /**
+ * see original {@link Mockito#when(Object)}
+ * @since 1.8.0
+ */
+ public static <T> BDDMyOngoingStubbing<T> given(T methodCall) {
+ return new BDDOngoingStubbingImpl<T>(Mockito.when(methodCall));
+ }
+
+ /**
+ * See original {@link Stubber}
+ * @since 1.8.0
+ */
+ public static interface BDDStubber {
+ /**
+ * See original {@link Stubber#doAnswer(Answer)}
+ * @since 1.8.0
+ */
+ BDDStubber willAnswer(Answer answer);
+
+ /**
+ * See original {@link Stubber#doNothing()}
+ * @since 1.8.0
+ */
+ BDDStubber willNothing();
+
+ /**
+ * See original {@link Stubber#doReturn(Object)}
+ * @since 1.8.0
+ */
+ BDDStubber willReturn(Object toBeReturned);
+
+ /**
+ * See original {@link Stubber#doThrow(Throwable)}
+ * @since 1.8.0
+ */
+ BDDStubber willThrow(Throwable toBeThrown);
+
+ /**
+ * See original {@link Stubber#doThrow(Class)}
+ * @since 1.9.0
+ */
+ BDDStubber willThrow(Class<? extends Throwable> toBeThrown);
+
+ /**
+ * See original {@link Stubber#doCallRealMethod()}
+ * @since 1.9.0
+ */
+ BDDStubber willCallRealMethod();
+
+ /**
+ * See original {@link Stubber#when(Object)}
+ * @since 1.8.0
+ */
+ <T> T given(T mock);
+ }
+
+ public static class BDDStubberImpl implements BDDStubber {
+
+ private final Stubber mockitoStubber;
+
+ public BDDStubberImpl(Stubber mockitoStubber) {
+ this.mockitoStubber = mockitoStubber;
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDStubber#given(java.lang.Object)
+ */
+ public <T> T given(T mock) {
+ return mockitoStubber.when(mock);
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDStubber#willAnswer(Answer)
+ */
+ public BDDStubber willAnswer(Answer answer) {
+ return new BDDStubberImpl(mockitoStubber.doAnswer(answer));
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDStubber#willNothing()
+ */
+ public BDDStubber willNothing() {
+ return new BDDStubberImpl(mockitoStubber.doNothing());
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDStubber#willReturn(java.lang.Object)
+ */
+ public BDDStubber willReturn(Object toBeReturned) {
+ return new BDDStubberImpl(mockitoStubber.doReturn(toBeReturned));
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDStubber#willThrow(java.lang.Throwable)
+ */
+ public BDDStubber willThrow(Throwable toBeThrown) {
+ return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown));
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDStubber#willThrow(Class)
+ */
+ public BDDStubber willThrow(Class<? extends Throwable> toBeThrown) {
+ return new BDDStubberImpl(mockitoStubber.doThrow(toBeThrown));
+ }
+
+ /* (non-Javadoc)
+ * @see BDDMockito.BDDStubber#willCallRealMethod()
+ */
+ public BDDStubber willCallRealMethod() {
+ return new BDDStubberImpl(mockitoStubber.doCallRealMethod());
+ }
+ }
+
+ /**
+ * see original {@link Mockito#doThrow(Throwable)}
+ * @since 1.8.0
+ */
+ public static BDDStubber willThrow(Throwable toBeThrown) {
+ return new BDDStubberImpl(Mockito.doThrow(toBeThrown));
+ }
+
+ /**
+ * see original {@link Mockito#doThrow(Throwable)}
+ * @since 1.9.0
+ */
+ public static BDDStubber willThrow(Class<? extends Throwable> toBeThrown) {
+ return new BDDStubberImpl(Mockito.doThrow(toBeThrown));
+ }
+
+ /**
+ * see original {@link Mockito#doAnswer(Answer)}
+ * @since 1.8.0
+ */
+ public static BDDStubber willAnswer(Answer answer) {
+ return new BDDStubberImpl(Mockito.doAnswer(answer));
+ }
+
+ /**
+ * see original {@link Mockito#doNothing()}
+ * @since 1.8.0
+ */
+ public static BDDStubber willDoNothing() {
+ return new BDDStubberImpl(Mockito.doNothing());
+ }
+
+ /**
+ * see original {@link Mockito#doReturn(Object)}
+ * @since 1.8.0
+ */
+ public static BDDStubber willReturn(Object toBeReturned) {
+ return new BDDStubberImpl(Mockito.doReturn(toBeReturned));
+ }
+
+ /**
+ * see original {@link Mockito#doCallRealMethod()}
+ * @since 1.8.0
+ */
+ public static BDDStubber willCallRealMethod() {
+ return new BDDStubberImpl(Mockito.doCallRealMethod());
+ }
+}
diff --git a/src/org/mockito/Captor.java b/src/org/mockito/Captor.java
new file mode 100644
index 0000000..30530fb
--- /dev/null
+++ b/src/org/mockito/Captor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import java.lang.annotation.*;
+
+/**
+ * Allows shorthand {@link org.mockito.ArgumentCaptor} creation on fields.
+ *
+ * <p>Example:
+ * <pre class="code"><code class="java">
+ * public class Test{
+ *
+ * @Captor ArgumentCaptor<AsyncCallback<Foo>> captor;
+ *
+ * @Before
+ * public void init(){
+ * MockitoAnnotations.initMocks(this);
+ * }
+ *
+ * @Test public void shouldDoSomethingUseful() {
+ * //...
+ * verify(mock.doStuff(captor.capture()));
+ * assertEquals("foo", captor.getValue());
+ * }
+ * }
+ * </code></pre>
+ *
+ * <p>
+ * One of the advantages of using @Captor annotation is that you can avoid warnings related capturing complex generic types.
+ *
+ * @see ArgumentCaptor
+ * @since 1.8.3
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Documented
+public @interface Captor {}
diff --git a/src/org/mockito/InOrder.java b/src/org/mockito/InOrder.java
new file mode 100644
index 0000000..5f19eb0
--- /dev/null
+++ b/src/org/mockito/InOrder.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito;
+
+import org.mockito.verification.VerificationMode;
+
+/**
+ * Allows verification in order. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * InOrder inOrder = inOrder(firstMock, secondMock);
+ *
+ * inOrder.verify(firstMock).add("was called first");
+ * inOrder.verify(secondMock).add("was called second");
+ * </code></pre>
+ *
+ * As of Mockito 1.8.4 you can verifyNoMoreInvocations() in order-sensitive way. Read more: {@link InOrder#verifyNoMoreInteractions()}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ */
+public interface InOrder {
+ /**
+ * Verifies interaction <b>happened once</b> in order.
+ * <p>
+ * Alias to <code>inOrder.verify(mock, times(1))</code>
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * InOrder inOrder = inOrder(firstMock, secondMock);
+ *
+ * inOrder.verify(firstMock).someMethod("was called first");
+ * inOrder.verify(secondMock).someMethod("was called second");
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mock to be verified
+ *
+ * @return mock object itself
+ */
+ <T> T verify(T mock);
+
+ /**
+ * Verifies interaction in order. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * InOrder inOrder = inOrder(firstMock, secondMock);
+ *
+ * inOrder.verify(firstMock, times(2)).someMethod("was called first two times");
+ * inOrder.verify(secondMock, atLeastOnce()).someMethod("was called second at least once");
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mock to be verified
+ * @param mode for example times(x) or atLeastOnce()
+ *
+ * @return mock object itself
+ */
+ <T> T verify(T mock, VerificationMode mode);
+
+
+ /**
+ * Verifies that no more interactions happened <b>in order</b>.
+ * Different from {@link Mockito#verifyNoMoreInteractions(Object...)} because the order of verification matters.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * mock.foo(); //1st
+ * mock.bar(); //2nd
+ * mock.baz(); //3rd
+ *
+ * InOrder inOrder = inOrder(mock);
+ *
+ * inOrder.verify(mock).bar(); //2n
+ * inOrder.verify(mock).baz(); //3rd (last method)
+ *
+ * //passes because there are no more interactions after last method:
+ * inOrder.verifyNoMoreInteractions();
+ *
+ * //however this fails because 1st method was not verified:
+ * Mockito.verifyNoMoreInteractions(mock);
+ * </code></pre>
+ */
+ void verifyNoMoreInteractions();
+}
\ No newline at end of file
diff --git a/src/org/mockito/Incubating.java b/src/org/mockito/Incubating.java
new file mode 100644
index 0000000..9748fd3
--- /dev/null
+++ b/src/org/mockito/Incubating.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * The annotation conveys following information:
+ * <ul>
+ * <li>The API is fairly new and we would appreciate your feedback. For example, what are you missing from the API
+ * to solve your use case (yes, please, real use cases).</li>
+ * <li>For types or methods that are already released this annotation means that that the API might change.
+ * The chance for that is small and we will always try to make any changes in a backwards compatible way.
+ * The only reason we would want to change it is to provide better support for using and extending Mockito.
+ * </li>
+ * <li>
+ * For types or methods that are not yet released it means the API is <strong>work in progress</strong>
+ * and can change before release.
+ * </li>
+ * </ul>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Incubating {
+}
diff --git a/src/org/mockito/InjectMocks.java b/src/org/mockito/InjectMocks.java
new file mode 100644
index 0000000..48341a9
--- /dev/null
+++ b/src/org/mockito/InjectMocks.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Mark a field on which injection should be performed.
+ *
+ * <ul>
+ * <li>Allows shorthand mock and spy injection.</li>
+ * <li>Minimizes repetitive mock and spy injection.</li>
+ * </ul>
+ * <p>
+ * Mockito will try to inject mocks only either by constructor injection,
+ * setter injection, or property injection in order and as described below.
+ * If any of the following strategy fail, then Mockito <strong>won't report failure</strong>;
+ * i.e. you will have to provide dependencies yourself.
+ * <ol>
+ * <li><strong>Constructor injection</strong>; the biggest constructor is chosen,
+ * then arguments are resolved with mocks declared in the test only.
+ * <p><u>Note:</u> If arguments can not be found, then null is passed.
+ * If non-mockable types are wanted, then constructor injection won't happen.
+ * In these cases, you will have to satisfy dependencies yourself.</p></li>
+ *
+ * <li><strong>Property setter injection</strong>; mocks will first be resolved by type,
+ * then, if there is several property of the same type, by the match of the property name and the mock name.
+ * <p><u>Note 1:</u> If you have properties with the same type (or same erasure), it's better to name all @Mock
+ * annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.</p>
+ * <p><u>Note 2:</u> If @InjectMocks instance wasn't initialized before and have a no-arg constructor,
+ * then it will be initialized with this constructor.</p></li>
+ *
+ * <li><strong>Field injection</strong>; mocks will first be resolved by type,
+ * then, if there is several property of the same type, by the match of the field name and the mock name.
+ * <p><u>Note 1:</u> If you have fields with the same type (or same erasure), it's better to name all @Mock
+ * annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.</p>
+ * <p><u>Note 2:</u> If @InjectMocks instance wasn't initialized before and have a no-arg constructor,
+ * then it will be initialized with this constructor.</p></li>
+ * </ol>
+ * </p>
+ *
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * public class ArticleManagerTest extends SampleBaseTestCase {
+ *
+ * @Mock private ArticleCalculator calculator;
+ * @Mock(name = "database") private ArticleDatabase dbMock; // note the mock name attribute
+ * @Spy private UserProvider userProvider = new ConsumerUserProvider();
+ *
+ * @InjectMocks private ArticleManager manager;
+ *
+ * @Test public void shouldDoSomething() {
+ * manager.initiateArticle();
+ * verify(database).addListener(any(ArticleListener.class));
+ * }
+ * }
+ *
+ * public class SampleBaseTestCase {
+ *
+ * @Before public void initMocks() {
+ * MockitoAnnotations.initMocks(this);
+ * }
+ * }
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * In the above example the field ArticleManager annotated with @InjectMocks can have
+ * a parameterized constructor only or a no-arg constructor only, or both.
+ * All these constructors can be package protected, protected or private, however
+ * <u>Mockito cannot instantiate inner classes, local classes, abstract classes and of course interfaces.</u>
+ * <u>Beware of private nest static classes too.</u>
+ *
+ * <p>The same stands for setters or fields, they can be declared with private
+ * visibility, Mockito will see them through reflection.
+ * However fields that are static or final will be ignored.</p>
+ *
+ * <p>So on the field that needs injection, for example constructor injection will happen here :</p>
+ * <pre class="code"><code class="java">
+ * public class ArticleManager {
+ * ArticleManager(ArticleCalculator calculator, ArticleDatabase database) {
+ * // parameterized constructor
+ * }
+ * }
+ * </code></pre>
+ *
+ * <p>Property setter injection will happen here :</p>
+ * <pre class="code"><code class="java">
+ * public class ArticleManager {
+ * // no-arg constructor
+ * ArticleManager() { }
+ *
+ * // setter
+ * void setDatabase(ArticleDatabase database) { }
+ *
+ * // setter
+ * void setCalculator(ArticleCalculator calculator) { }
+ * }
+ * </code></pre>
+ *
+ * <p>Field injection will be used here :</p>
+ * <pre class="code"><code class="java">
+ * public class ArticleManager {
+ * private ArticleDatabase database;
+ * private ArticleCalculator calculator;
+ * }
+ * </code></pre>
+ * </p>
+ *
+ * <p>And finally, no injection will happen on the type in this case:</p>
+ * <pre class="code"><code class="java">
+ * public class ArticleManager {
+ * private ArticleDatabase database;
+ * private ArticleCalculator calculator;
+ *
+ * ArticleManager(ArticleObserver observer, boolean flag) {
+ * // observer is not declared in the test above.
+ * // flag is not mockable anyway
+ * }
+ * }
+ * </code></pre>
+ * </p>
+ *
+ *
+ * <p>
+ * Again, note that @InjectMocks will only inject mocks/spies created using the @Spy or @Mock annotation.
+ * </p>
+ *
+ * <p>
+ * <strong><code>MockitoAnnotations.initMocks(this)</code></strong> method has to be called to initialize annotated objects.
+ * In above example, <code>initMocks()</code> is called in @Before (JUnit4) method of test's base class.
+ * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class.
+ * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (@RunWith) or use the built-in
+ * {@link org.mockito.runners.MockitoJUnitRunner}.
+ * </p>
+ *
+ * @see Mock
+ * @see Spy
+ * @see MockitoAnnotations#initMocks(Object)
+ * @see org.mockito.runners.MockitoJUnitRunner
+ * @since 1.8.3
+ */
+@Documented
+@Target(FIELD)
+@Retention(RUNTIME)
+public @interface InjectMocks {}
diff --git a/src/org/mockito/Matchers.java b/src/org/mockito/Matchers.java
new file mode 100644
index 0000000..9e227cd
--- /dev/null
+++ b/src/org/mockito/Matchers.java
@@ -0,0 +1,880 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.hamcrest.Matcher;
+import org.mockito.internal.matchers.*;
+import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
+import org.mockito.internal.progress.HandyReturnValues;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Allow flexible verification or stubbing. See also {@link AdditionalMatchers}.
+ * <p>
+ * {@link Mockito} extends Matchers so to get access to all matchers just import Mockito class statically.
+ * <pre class="code"><code class="java">
+ * //stubbing using anyInt() argument matcher
+ * when(mockedList.get(anyInt())).thenReturn("element");
+ *
+ * //following prints "element"
+ * System.out.println(mockedList.get(999));
+ *
+ * //you can also verify using argument matcher
+ * verify(mockedList).get(anyInt());
+ * </code></pre>
+ * Scroll down to see all methods - full list of matchers.
+ * <p>
+ * <b>Warning:</b>
+ * <p>
+ * If you are using argument matchers, <b>all arguments</b> have to be provided by matchers.
+ * <p>
+ * E.g: (example shows verification but the same applies to stubbing):
+ * <pre class="code"><code class="java">
+ * verify(mock).someMethod(anyInt(), anyString(), <b>eq("third argument")</b>);
+ * //above is correct - eq() is also an argument matcher
+ *
+ * verify(mock).someMethod(anyInt(), anyString(), <b>"third argument"</b>);
+ * //above is incorrect - exception will be thrown because third argument is given without argument matcher.
+ * </code></pre>
+ * <p>
+ * Matcher methods like <code>anyObject()</code>, <code>eq()</code> <b>do not</b> return matchers.
+ * Internally, they record a matcher on a stack and return a dummy value (usually null).
+ * This implementation is due static type safety imposed by java compiler.
+ * The consequence is that you cannot use <code>anyObject()</code>, <code>eq()</code> methods outside of verified/stubbed method.
+ *
+ * <p>
+ * <b>Warning 2:</b>
+ * <p>
+ * The any family methods <b>*don't do any type checks*</b>, those are only here to avoid casting
+ * in your code. If you want to perform type checks use the {@link #isA(Class)} method.
+ * This <b>might</b> however change (type checks could be added) in a future major release.
+ *
+ * <h1>Custom Argument Matchers</h1>
+ *
+ * Use {@link Matchers#argThat} method and pass an instance of hamcrest {@link Matcher}.
+ * <p>
+ * Before you start implementing your own custom argument matcher, make sure you check out {@link ArgumentCaptor} api.
+ * <p>
+ * So, how to implement your own argument matcher?
+ * First, you might want to subclass {@link ArgumentMatcher} which is an hamcrest matcher with predefined describeTo() method.
+ * Default description generated by describeTo() uses <b>decamelized class name</b> - to promote meaningful class names.
+ * <p>
+ * Example:
+ *
+ * <pre class="code"><code class="java">
+ * class IsListOfTwoElements extends ArgumentMatcher<List> {
+ * public boolean matches(Object list) {
+ * return ((List) list).size() == 2;
+ * }
+ * }
+ *
+ * List mock = mock(List.class);
+ *
+ * when(mock.addAll(argThat(new IsListOfTwoElements()))).thenReturn(true);
+ *
+ * mock.addAll(Arrays.asList("one", "two"));
+ *
+ * verify(mock).addAll(argThat(new IsListOfTwoElements()));
+ * </code></pre>
+ *
+ * To keep it readable you may want to extract method, e.g:
+ * <pre class="code"><code class="java">
+ * verify(mock).addAll(<b>argThat(new IsListOfTwoElements())</b>);
+ * //becomes
+ * verify(mock).addAll(<b>listOfTwoElements()</b>);
+ * </code></pre>
+ *
+ * <b>Warning:</b> Be reasonable with using complicated argument matching, especially custom argument matchers, as it can make the test less readable.
+ * Sometimes it's better to implement equals() for arguments that are passed to mocks
+ * (Mockito naturally uses equals() for argument matching).
+ * This can make the test cleaner.
+ * <p>
+ * Also, <b>sometimes {@link ArgumentCaptor} may be a better fit</b> than custom matcher.
+ * For example, if custom argument matcher is not likely to be reused
+ * or you just need it to assert on argument values to complete verification of behavior.
+ */
+@SuppressWarnings("unchecked")
+public class Matchers {
+
+ private static MockingProgress mockingProgress = new ThreadSafeMockingProgress();
+
+ /**
+ * Any <code>boolean</code>, <code>Boolean</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>false</code>.
+ */
+ public static boolean anyBoolean() {
+ return reportMatcher(Any.ANY).returnFalse();
+ }
+
+ /**
+ * Any <code>byte</code>, <code>Byte</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>0</code>.
+ */
+ public static byte anyByte() {
+ return reportMatcher(Any.ANY).returnZero();
+ }
+
+ /**
+ * Any <code>char</code>, <code>Character</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>0</code>.
+ */
+ public static char anyChar() {
+ return reportMatcher(Any.ANY).returnChar();
+ }
+
+ /**
+ * Any int, Integer or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>0</code>.
+ */
+ public static int anyInt() {
+ return reportMatcher(Any.ANY).returnZero();
+ }
+
+ /**
+ * Any <code>long</code>, <code>Long</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>0</code>.
+ */
+ public static long anyLong() {
+ return reportMatcher(Any.ANY).returnZero();
+ }
+
+ /**
+ * Any <code>float</code>, <code>Float</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>0</code>.
+ */
+ public static float anyFloat() {
+ return reportMatcher(Any.ANY).returnZero();
+ }
+
+ /**
+ * Any <code>double</code>, <code>Double</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>0</code>.
+ */
+ public static double anyDouble() {
+ return reportMatcher(Any.ANY).returnZero();
+ }
+
+ /**
+ * Any <code>short</code>, <code>Short</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>0</code>.
+ */
+ public static short anyShort() {
+ return reportMatcher(Any.ANY).returnZero();
+ }
+
+ /**
+ * Any <code>Object</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * Has aliases: {@link #any()} and {@link #any(Class clazz)}
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>null</code>.
+ */
+ public static <T> T anyObject() {
+ return (T) reportMatcher(Any.ANY).returnNull();
+ }
+
+ /**
+ * Any vararg, meaning any number and values of arguments.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * //verification:
+ * mock.foo(1, 2);
+ * mock.foo(1, 2, 3, 4);
+ *
+ * verify(mock, times(2)).foo(anyVararg());
+ *
+ * //stubbing:
+ * when(mock.foo(anyVararg()).thenReturn(100);
+ *
+ * //prints 100
+ * System.out.println(mock.foo(1, 2));
+ * //also prints 100
+ * System.out.println(mock.foo(1, 2, 3, 4));
+ * </code></pre>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>null</code>.
+ */
+ public static <T> T anyVararg() {
+ return (T) reportMatcher(AnyVararg.ANY_VARARG).returnNull();
+ }
+
+ /**
+ * Any kind object, not necessary of the given class.
+ * The class argument is provided only to avoid casting.
+ * <p>
+ * Sometimes looks better than <code>anyObject()</code> - especially when explicit casting is required
+ * <p>
+ * Alias to {@link Matchers#anyObject()}
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param clazz The type to avoid casting
+ * @return <code>null</code>.
+ */
+ public static <T> T any(Class<T> clazz) {
+ return (T) reportMatcher(Any.ANY).returnFor(clazz);
+ }
+
+ /**
+ * Any object or <code>null</code>.
+ * <p>
+ * Shorter alias to {@link Matchers#anyObject()}
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>null</code>.
+ */
+ public static <T> T any() {
+ return (T) anyObject();
+ }
+
+ /**
+ * Any <code>String</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return empty String ("")
+ */
+ public static String anyString() {
+ return reportMatcher(Any.ANY).returnString();
+ }
+
+ /**
+ * Any <code>List</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return empty List.
+ */
+ public static List anyList() {
+ return reportMatcher(Any.ANY).returnList();
+ }
+
+ /**
+ * Generic friendly alias to {@link Matchers#anyList()}.
+ * It's an alternative to @SuppressWarnings("unchecked") to keep code clean of compiler warnings.
+ * <p>
+ * Any <code>List</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param clazz Type owned by the list to avoid casting
+ * @return empty List.
+ */
+ public static <T> List<T> anyListOf(Class<T> clazz) {
+ return (List) reportMatcher(Any.ANY).returnList();
+ }
+
+ /**
+ * Any <code>Set</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return empty Set
+ */
+ public static Set anySet() {
+ return reportMatcher(Any.ANY).returnSet();
+ }
+
+ /**
+ * Generic friendly alias to {@link Matchers#anySet()}.
+ * It's an alternative to @SuppressWarnings("unchecked") to keep code clean of compiler warnings.
+ * <p>
+ * Any <code>Set</code> or <code>null</code>
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param clazz Type owned by the Set to avoid casting
+ * @return empty Set
+ */
+ public static <T> Set<T> anySetOf(Class<T> clazz) {
+ return (Set) reportMatcher(Any.ANY).returnSet();
+ }
+
+ /**
+ * Any <code>Map</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return empty Map.
+ */
+ public static Map anyMap() {
+ return reportMatcher(Any.ANY).returnMap();
+ }
+
+ /**
+ * Generic friendly alias to {@link Matchers#anyMap()}.
+ * It's an alternative to @SuppressWarnings("unchecked") to keep code clean of compiler warnings.
+ * <p>
+ * Any <code>Map</code> or <code>null</code>
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param keyClazz Type of the map key to avoid casting
+ * @param valueClazz Type of the value to avoid casting
+ * @return empty Map.
+ */
+ public static <K, V> Map<K, V> anyMapOf(Class<K> keyClazz, Class<V> valueClazz) {
+ return reportMatcher(Any.ANY).returnMap();
+ }
+
+ /**
+ * Any <code>Collection</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return empty Collection.
+ */
+ public static Collection anyCollection() {
+ return reportMatcher(Any.ANY).returnList();
+ }
+
+ /**
+ * Generic friendly alias to {@link Matchers#anyCollection()}.
+ * It's an alternative to @SuppressWarnings("unchecked") to keep code clean of compiler warnings.
+ * <p>
+ * Any <code>Collection</code> or <code>null</code>.
+ * <p>
+ * This method <b>*don'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.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param clazz Type owned by the collection to avoid casting
+ * @return empty Collection.
+ */
+ public static <T> Collection<T> anyCollectionOf(Class<T> clazz) {
+ return (Collection) reportMatcher(Any.ANY).returnList();
+ }
+
+ /**
+ * <code>Object</code> argument that implements the given class.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param <T>
+ * the accepted type.
+ * @param clazz
+ * the class of the accepted type.
+ * @return <code>null</code>.
+ */
+ public static <T> T isA(Class<T> clazz) {
+ return reportMatcher(new InstanceOf(clazz)).<T>returnFor(clazz);
+ }
+
+ /**
+ * <code>boolean</code> argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static boolean eq(boolean value) {
+ return reportMatcher(new Equals(value)).returnFalse();
+ }
+
+ /**
+ * <code>byte</code> argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static byte eq(byte value) {
+ return reportMatcher(new Equals(value)).returnZero();
+ }
+
+ /**
+ * <code>char</code> argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static char eq(char value) {
+ return reportMatcher(new Equals(value)).returnChar();
+ }
+
+ /**
+ * <code>double</code> argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static double eq(double value) {
+ return reportMatcher(new Equals(value)).returnZero();
+ }
+
+ /**
+ * <code>float</code> argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static float eq(float value) {
+ return reportMatcher(new Equals(value)).returnZero();
+ }
+
+ /**
+ * <code>int</code> argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static int eq(int value) {
+ return reportMatcher(new Equals(value)).returnZero();
+ }
+
+ /**
+ * <code>long</code> argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static long eq(long value) {
+ return reportMatcher(new Equals(value)).returnZero();
+ }
+
+ /**
+ * <code>short</code> argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>0</code>.
+ */
+ public static short eq(short value) {
+ return reportMatcher(new Equals(value)).returnZero();
+ }
+
+ /**
+ * Object argument that is equal to the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @return <code>null</code>.
+ */
+ public static <T> T eq(T value) {
+ return (T) reportMatcher(new Equals(value)).<T>returnFor(value);
+ }
+
+ /**
+ * Object argument that is reflection-equal to the given value with support for excluding
+ * selected fields from a class.
+ * <p>
+ * This matcher can be used when equals() is not implemented on compared objects.
+ * Matcher uses java reflection API to compare fields of wanted and actual object.
+ * <p>
+ * Works similarly to EqualsBuilder.reflectionEquals(this, other, exlucdeFields) from
+ * apache commons library.
+ * <p>
+ * <b>Warning</b> The equality check is shallow!
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param value
+ * the given value.
+ * @param excludeFields
+ * fields to exclude, if field does not exist it is ignored.
+ * @return <code>null</code>.
+ */
+ public static <T> T refEq(T value, String... excludeFields) {
+ return reportMatcher(new ReflectionEquals(value, excludeFields)).<T>returnNull();
+ }
+
+ /**
+ * Object argument that is the same as the given value.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param <T>
+ * the type of the object, it is passed through to prevent casts.
+ * @param value
+ * the given value.
+ * @return <code>null</code>.
+ */
+ public static <T> T same(T value) {
+ return (T) reportMatcher(new Same(value)).<T>returnFor(value);
+ }
+
+ /**
+ * <code>null</code> argument.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>null</code>.
+ */
+ public static Object isNull() {
+ return reportMatcher(Null.NULL).returnNull();
+ }
+
+ /**
+ * <code>null</code> argument.
+ * The class argument is provided to avoid casting.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param clazz Type to avoid casting
+ * @return <code>null</code>.
+ */
+ public static <T> T isNull(Class<T> clazz) {
+ return (T) reportMatcher(Null.NULL).returnNull();
+ }
+
+ /**
+ * Not <code>null</code> argument.
+ * <p>
+ * alias to {@link Matchers#isNotNull()}
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>null</code>.
+ */
+ public static Object notNull() {
+ return reportMatcher(NotNull.NOT_NULL).returnNull();
+ }
+
+ /**
+ * Not <code>null</code> argument, not necessary of the given class.
+ * The class argument is provided to avoid casting.
+ * <p>
+ * alias to {@link Matchers#isNotNull(Class)}
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param clazz Type to avoid casting
+ * @return <code>null</code>.
+ */
+ public static <T> T notNull(Class<T> clazz) {
+ return (T) reportMatcher(NotNull.NOT_NULL).returnNull();
+ }
+
+ /**
+ * Not <code>null</code> argument.
+ * <p>
+ * alias to {@link Matchers#notNull()}
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @return <code>null</code>.
+ */
+ public static Object isNotNull() {
+ return notNull();
+ }
+
+ /**
+ * Not <code>null</code> argument, not necessary of the given class.
+ * The class argument is provided to avoid casting.
+ * <p>
+ * alias to {@link Matchers#notNull(Class)}
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param clazz Type to avoid casting
+ * @return <code>null</code>.
+ */
+ public static <T> T isNotNull(Class<T> clazz) {
+ return notNull(clazz);
+ }
+
+ /**
+ * <code>String</code> argument that contains the given substring.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param substring
+ * the substring.
+ * @return empty String ("").
+ */
+ public static String contains(String substring) {
+ return reportMatcher(new Contains(substring)).returnString();
+ }
+
+ /**
+ * <code>String</code> argument that matches the given regular expression.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param regex
+ * the regular expression.
+ * @return empty String ("").
+ */
+ public static String matches(String regex) {
+ return reportMatcher(new Matches(regex)).returnString();
+ }
+
+ /**
+ * <code>String</code> argument that ends with the given suffix.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param suffix
+ * the suffix.
+ * @return empty String ("").
+ */
+ public static String endsWith(String suffix) {
+ return reportMatcher(new EndsWith(suffix)).returnString();
+ }
+
+ /**
+ * <code>String</code> argument that starts with the given prefix.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param prefix
+ * the prefix.
+ * @return empty String ("").
+ */
+ public static String startsWith(String prefix) {
+ return reportMatcher(new StartsWith(prefix)).returnString();
+ }
+
+ /**
+ * Allows creating custom argument matchers.
+ * <p>
+ * In rare cases when the parameter is a primitive then you <b>*must*</b> use relevant intThat(), floatThat(), etc. method.
+ * This way you will avoid <code>NullPointerException</code> during auto-unboxing.
+ * <p>
+ * See examples in javadoc for {@link ArgumentMatcher} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>null</code>.
+ */
+ public static <T> T argThat(Matcher<T> matcher) {
+ return reportMatcher(matcher).<T>returnNull();
+ }
+
+ /**
+ * Allows creating custom <code>Character</code> argument matchers.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>0</code>.
+ */
+ public static char charThat(Matcher<Character> matcher) {
+ return reportMatcher(matcher).returnChar();
+ }
+
+ /**
+ * Allows creating custom <code>Boolean</code> argument matchers.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>false</code>.
+ */
+ public static boolean booleanThat(Matcher<Boolean> matcher) {
+ return reportMatcher(matcher).returnFalse();
+ }
+
+ /**
+ * Allows creating custom <code>Byte</code> argument matchers.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>0</code>.
+ */
+ public static byte byteThat(Matcher<Byte> matcher) {
+ return reportMatcher(matcher).returnZero();
+ }
+
+ /**
+ * Allows creating custom <code>Short</code> argument matchers.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>0</code>.
+ */
+ public static short shortThat(Matcher<Short> matcher) {
+ return reportMatcher(matcher).returnZero();
+ }
+
+ /**
+ * Allows creating custom <code>Integer</code> argument matchers.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>0</code>.
+ */
+ public static int intThat(Matcher<Integer> matcher) {
+ return reportMatcher(matcher).returnZero();
+ }
+
+ /**
+ * Allows creating custom <code>Long</code> argument matchers.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>0</code>.
+ */
+ public static long longThat(Matcher<Long> matcher) {
+ return reportMatcher(matcher).returnZero();
+ }
+
+ /**
+ * Allows creating custom <code>Float</code> argument matchers.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>0</code>.
+ */
+ public static float floatThat(Matcher<Float> matcher) {
+ return reportMatcher(matcher).returnZero();
+ }
+
+ /**
+ * Allows creating custom <code>Double</code> argument matchers.
+ * <p>
+ * See examples in javadoc for {@link Matchers} class
+ *
+ * @param matcher decides whether argument matches
+ * @return <code>0</code>.
+ */
+ public static double doubleThat(Matcher<Double> matcher) {
+ return reportMatcher(matcher).returnZero();
+ }
+
+ private static HandyReturnValues reportMatcher(Matcher<?> matcher) {
+ return mockingProgress.getArgumentMatcherStorage().reportMatcher(matcher);
+ }
+}
diff --git a/src/org/mockito/Mock.java b/src/org/mockito/Mock.java
new file mode 100644
index 0000000..baf1c25
--- /dev/null
+++ b/src/org/mockito/Mock.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Mark a field as a mock.
+ *
+ * <ul>
+ * <li>Allows shorthand mock creation.</li>
+ * <li>Minimizes repetitive mock creation code.</li>
+ * <li>Makes the test class more readable.</li>
+ * <li>Makes the verification error easier to read because the <b>field name</b> is used to identify the mock.</li>
+ * </ul>
+ *
+ * <pre class="code"><code class="java">
+ * public class ArticleManagerTest extends SampleBaseTestCase {
+ *
+ * @Mock private ArticleCalculator calculator;
+ * @Mock(name = "database") private ArticleDatabase dbMock;
+ * @Mock(answer = RETURNS_MOCKS) private UserProvider userProvider;
+ * @Mock(extraInterfaces = {Queue.class, Observer.class}) private articleMonitor;
+ *
+ * private ArticleManager manager;
+ *
+ * @Before public void setup() {
+ * manager = new ArticleManager(userProvider, database, calculator, articleMonitor);
+ * }
+ * }
+ *
+ * public class SampleBaseTestCase {
+ *
+ * @Before public void initMocks() {
+ * MockitoAnnotations.initMocks(this);
+ * }
+ * }
+ * </code></pre>
+ *
+ * <p>
+ * <strong><code>MockitoAnnotations.initMocks(this)</code></strong> method has to be called to initialize annotated objects.
+ * In above example, <code>initMocks()</code> is called in @Before (JUnit4) method of test's base class.
+ * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class.
+ * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (@RunWith) or use the built-in
+ * {@link org.mockito.runners.MockitoJUnitRunner}.
+ * </p>
+ *
+ * @see Mockito#mock(Class)
+ * @see Spy
+ * @see InjectMocks
+ * @see MockitoAnnotations#initMocks(Object)
+ * @see org.mockito.runners.MockitoJUnitRunner
+ */
+@Target(FIELD)
+@Retention(RUNTIME)
+@Documented
+public @interface Mock {
+
+ Answers answer() default Answers.RETURNS_DEFAULTS;
+
+ String name() default "";
+
+ Class<?>[] extraInterfaces() default {};
+
+ boolean serializable() default false;
+}
diff --git a/src/org/mockito/MockSettings.java b/src/org/mockito/MockSettings.java
new file mode 100644
index 0000000..7f84b1c
--- /dev/null
+++ b/src/org/mockito/MockSettings.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.listeners.InvocationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+
+/**
+ * Allows mock creation with additional mock settings.
+ * <p/>
+ * Don't use it too often.
+ * Consider writing simple tests that use simple mocks.
+ * Repeat after me: simple tests push simple, KISSy, readable & maintainable code.
+ * If you cannot write a test in a simple way - refactor the code under test.
+ * <p/>
+ * Examples of mock settings:
+ * <pre class="code"><code class="java">
+ * //Creates mock with different default answer & name
+ * Foo mock = mock(Foo.class, withSettings()
+ * .defaultAnswer(RETURNS_SMART_NULLS)
+ * .name("cool mockie")
+ * );
+ *
+ * //Creates mock with different default answer, descriptive name and extra interfaces
+ * Foo mock = mock(Foo.class, withSettings()
+ * .defaultAnswer(RETURNS_SMART_NULLS)
+ * .name("cool mockie")
+ * .extraInterfaces(Bar.class));
+ * </code></pre>
+ * {@link MockSettings} has been introduced for two reasons.
+ * Firstly, to make it easy to add another mock setting when the demand comes.
+ * Secondly, to enable combining together different mock settings without introducing zillions of overloaded mock() methods.
+ */
+public interface MockSettings extends Serializable {
+
+ /**
+ * Specifies extra interfaces the mock should implement. Might be useful for legacy code or some corner cases.
+ * For background, see issue 51 <a href="http://code.google.com/p/mockito/issues/detail?id=51">here</a>
+ * <p>
+ * This mysterious feature should be used very occasionally.
+ * The object under test should know exactly its collaborators & dependencies.
+ * If you happen to use it often than please make sure you are really producing simple, clean & readable code.
+ * <p>
+ * Examples:
+ * <pre class="code"><code class="java">
+ * Foo foo = mock(Foo.class, withSettings().extraInterfaces(Bar.class, Baz.class));
+ *
+ * //now, the mock implements extra interfaces, so following casting is possible:
+ * Bar bar = (Bar) foo;
+ * Baz baz = (Baz) foo;
+ * </code></pre>
+ *
+ * @param interfaces extra interfaces the should implement.
+ * @return settings instance so that you can fluently specify other settings
+ */
+ MockSettings extraInterfaces(Class<?>... interfaces);
+
+ /**
+ * Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors.
+ * <p>
+ * Beware that naming mocks is not a solution for complex code which uses too many mocks or collaborators.
+ * <b>If you have too many mocks then refactor the code</b> so that it's easy to test/debug without necessity of naming mocks.
+ * <p>
+ * <b>If you use @Mock annotation then you've got naming mocks for free!</b> @Mock uses field name as mock name. {@link Mock Read more.}
+ * <p>
+ * Examples:
+ * <pre class="code"><code class="java">
+ * Foo foo = mock(Foo.class, withSettings().name("foo"));
+ *
+ * //Below does exactly the same:
+ * Foo foo = mock(Foo.class, "foo");
+ * </code></pre>
+ * @param name the name of the mock, later used in all verification errors
+ * @return settings instance so that you can fluently specify other settings
+ */
+ MockSettings name(String name);
+
+ /**
+ * Specifies the instance to spy on. Makes sense only for spies/partial mocks.
+ *
+ * Sets the instance that will be spied. Actually copies the internal fields of the passed instance to the mock.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more or less about tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ * <p>
+ * Enough warnings about partial mocks, see an example how spiedInstance() works:
+ * <pre class="code"><code class="java">
+ * Foo foo = mock(Foo.class, withSettings().spiedInstance(fooInstance));
+ *
+ * //Below does exactly the same:
+ * Foo foo = spy(fooInstance);
+ * </code></pre>
+ *
+ * About stubbing for a partial mock, as it is a spy it will always call the real method, unless you use the
+ * <code>doReturn</code>|<code>Throw</code>|<code>Answer</code>|<code>CallRealMethod</code> stubbing style. Example:
+ *
+ * <pre class="code"><code class="java">
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ * when(spy.get(0)).thenReturn("foo");
+ *
+ * //You have to use doReturn() for stubbing
+ * doReturn("foo").when(spy).get(0);
+ * </code>
+ *
+ * @param instance to spy on
+ * @return settings instance so that you can fluently specify other settings
+ */
+ MockSettings spiedInstance(Object instance);
+
+ /**
+ * Specifies default answers to interactions.
+ * It's quite advanced feature and typically you don't need it to write decent tests.
+ * However it can be helpful when working with legacy systems.
+ * <p>
+ * It is the default answer so it will be used <b>only when you don't</b> stub the method call.
+ *
+ * <pre class="code"><code class="java">
+ * Foo mock = mock(Foo.class, withSettings().defaultAnswer(RETURNS_SMART_NULLS));
+ * Foo mockTwo = mock(Foo.class, withSettings().defaultAnswer(new YourOwnAnswer()));
+ *
+ * //Below does exactly the same:
+ * Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
+ * </code></pre>
+ *
+ * @param defaultAnswer default answer to be used by mock when not stubbed
+ * @return settings instance so that you can fluently specify other settings
+ */
+ @SuppressWarnings("unchecked")
+ MockSettings defaultAnswer(Answer defaultAnswer);
+
+ /**
+ * Configures the mock to be serializable. With this feature you can use a mock in a place that requires dependencies to be serializable.
+ * <p>
+ * WARNING: This should be rarely used in unit testing.
+ * <p>
+ * The behaviour was implemented for a specific use case of a BDD spec that had an unreliable external dependency. This
+ * was in a web environment and the objects from the external dependency were being serialized to pass between layers.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * List serializableMock = mock(List.class, withSettings().serializable());
+ * </code></pre>
+ *
+ * @return settings instance so that you can fluently specify other settings
+ * @since 1.8.1
+ */
+ MockSettings serializable();
+
+ /**
+ * Enables real-time logging of method invocations on this mock. Can be used
+ * during test debugging in order to find wrong interactions with this mock.
+ * <p>
+ * Invocations are logged as they happen to the standard output stream.
+ * <p>
+ * Calling this method multiple times makes no difference.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * List mockWithLogger = mock(List.class, withSettings().verboseLogging());
+ * </code></pre>
+ *
+ * @return settings instance so that you can fluently specify other settings
+ */
+ MockSettings verboseLogging();
+
+ /**
+ * Registers a listener for method invocations on this mock. The listener is
+ * notified every time a method on this mock is called.
+ * <p>
+ * Multiple listeners may be added, but the same object is only added once.
+ * The order, in which the listeners are added, is not guaranteed to be the
+ * order in which the listeners are notified.
+ *
+ * Example:
+ * <pre class="code"><code class="java">
+ * List mockWithListener = mock(List.class, withSettings().invocationListeners(new YourInvocationListener()));
+ * </code></pre>
+ *
+ * See the {@link InvocationListener listener interface} for more details.
+ *
+ * @param listeners The invocation listeners to add. May not be null.
+ * @return settings instance so that you can fluently specify other settings
+ */
+ MockSettings invocationListeners(InvocationListener... listeners);
+
+ /**
+ * Sets whether this mock should only provide stubbing of methods.
+ * A stub-only mock does not record method
+ * invocations, thus saving memory but
+ * disallowing verification of invocations.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * List stubOnly = mock(List.class, withSettings().stubOnly());
+ * </code></pre>
+ *
+ * @return settings instance so that you can fluently specify other settings
+ */
+ MockSettings stubOnly();}
diff --git a/src/org/mockito/MockingDetails.java b/src/org/mockito/MockingDetails.java
new file mode 100644
index 0000000..b00e23a
--- /dev/null
+++ b/src/org/mockito/MockingDetails.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+/**
+ * Provides mocking information.
+ * For example, you can identify whether a particular object is either a mock or a spy.
+ *
+ * @since 1.9.5
+ */
+@Incubating
+public interface MockingDetails {
+
+ /**
+ * Informs if the object is a mock.
+ * @return true if the object is a mock or a spy.
+ *
+ * @since 1.9.5
+ */
+ boolean isMock();
+
+ /**
+ * Informs if the object is a spy.
+ * @return true if the object is a spy.
+ *
+ * @since 1.9.5
+ */
+ boolean isSpy();
+}
\ No newline at end of file
diff --git a/src/org/mockito/Mockito.java b/src/org/mockito/Mockito.java
new file mode 100644
index 0000000..a39917f
--- /dev/null
+++ b/src/org/mockito/Mockito.java
@@ -0,0 +1,2171 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import org.mockito.internal.MockitoCore;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.debugging.MockitoDebuggerImpl;
+import org.mockito.internal.stubbing.answers.*;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsMoreEmptyValues;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.*;
+import org.mockito.verification.Timeout;
+import org.mockito.verification.VerificationMode;
+import org.mockito.verification.VerificationWithTimeout;
+
+/**
+ * <p align="left"><img src="logo.jpg"/></p>
+ * Mockito library enables mocks creation, verification and stubbing.
+ * <p>
+ * This javadoc content is also available on the <a href="http://mockito.org">http://mockito.org</a> web page.
+ * All documentation is kept in javadocs because it guarantees consistency between what's on the web and what's in the source code.
+ * Also, it makes possible to access documentation straight from the IDE even if you work offline.
+ *
+ * <h1>Contents</h1>
+ *
+ * <b>
+ * <a href="#1">1. Let's verify some behaviour! </a><br/>
+ * <a href="#2">2. How about some stubbing? </a><br/>
+ * <a href="#3">3. Argument matchers </a><br/>
+ * <a href="#4">4. Verifying exact number of invocations / at least once / never </a><br/>
+ * <a href="#5">5. Stubbing void methods with exceptions </a><br/>
+ * <a href="#6">6. Verification in order </a><br/>
+ * <a href="#7">7. Making sure interaction(s) never happened on mock </a><br/>
+ * <a href="#8">8. Finding redundant invocations </a><br/>
+ * <a href="#9">9. Shorthand for mocks creation - <code>@Mock</code> annotation </a><br/>
+ * <a href="#10">10. Stubbing consecutive calls (iterator-style stubbing) </a><br/>
+ * <a href="#11">11. Stubbing with callbacks </a><br/>
+ * <a href="#12">12. <code>doReturn()</code>|<code>doThrow()</code>|<code>doAnswer()</code>|<code>doNothing()</code>|<code>doCallRealMethod()</code> family of methods</a><br/>
+ * <a href="#13">13. Spying on real objects </a><br/>
+ * <a href="#14">14. Changing default return values of unstubbed invocations (Since 1.7) </a><br/>
+ * <a href="#15">15. Capturing arguments for further assertions (Since 1.8.0) </a><br/>
+ * <a href="#16">16. Real partial mocks (Since 1.8.0) </a><br/>
+ * <a href="#17">17. Resetting mocks (Since 1.8.0) </a><br/>
+ * <a href="#18">18. Troubleshooting & validating framework usage (Since 1.8.0) </a><br/>
+ * <a href="#19">19. Aliases for behavior driven development (Since 1.8.0) </a><br/>
+ * <a href="#20">20. Serializable mocks (Since 1.8.1) </a><br/>
+ * <a href="#21">21. New annotations: <code>@Captor</code>, <code>@Spy</code>, <code>@InjectMocks</code> (Since 1.8.3) </a><br/>
+ * <a href="#22">22. Verification with timeout (Since 1.8.5) </a><br/>
+ * <a href="#23">23. (New) Automatic instantiation of <code>@Spies</code>, <code>@InjectMocks</code> and constructor injection goodness (Since 1.9.0)</a><br/>
+ * <a href="#24">24. (New) One-liner stubs (Since 1.9.0)</a><br/>
+ * <a href="#25">25. (New) Verification ignoring stubs (Since 1.9.0)</a><br/>
+ * <a href="#26">26. (**New**) Mocking details (Since 1.9.5)</a><br/>
+ * <a href="#27">27. (**New**) Delegate calls to real instance (Since 1.9.5)</a><br/>
+ * <a href="#28">28. (**New**) <code>MockMaker</code> API (Since 1.9.5)</a><br/>
+ * </b>
+ *
+ * <p>
+ * Following examples mock a List, because everyone knows its interface (methods
+ * like <code>add()</code>, <code>get()</code>, <code>clear()</code> will be used). <br>
+ * You probably wouldn't mock List class 'in real'.
+ *
+ *
+ *
+ *
+ * <h3 id="1">1. <a class="meaningful_link" href="#verification">Let's verify some behaviour!</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * //Let's import Mockito statically so that the code looks clearer
+ * import static org.mockito.Mockito.*;
+ *
+ * //mock creation
+ * List mockedList = mock(List.class);
+ *
+ * //using mock object
+ * mockedList.add("one");
+ * mockedList.clear();
+ *
+ * //verification
+ * verify(mockedList).add("one");
+ * verify(mockedList).clear();
+ * </code></pre>
+ *
+ * <p>
+ * Once created, mock will remember all interactions. Then you can selectively
+ * verify whatever interaction you are interested in.
+ *
+ *
+ *
+ *
+ * <h3 id="2">2. <a class="meaningful_link" href="#stubbing">How about some stubbing?</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * //You can mock concrete classes, not only interfaces
+ * LinkedList mockedList = mock(LinkedList.class);
+ *
+ * //stubbing
+ * when(mockedList.get(0)).thenReturn("first");
+ * when(mockedList.get(1)).thenThrow(new RuntimeException());
+ *
+ * //following prints "first"
+ * System.out.println(mockedList.get(0));
+ *
+ * //following throws runtime exception
+ * System.out.println(mockedList.get(1));
+ *
+ * //following prints "null" because get(999) was not stubbed
+ * System.out.println(mockedList.get(999));
+ *
+ * //Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>
+ * //If your code cares what get(0) returns then something else breaks (often before even verify() gets executed).
+ * //If your code doesn't care what get(0) returns then it should not be stubbed. Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.
+ * verify(mockedList).get(0);
+ * </code></pre>
+ *
+ * <ul>
+ * <li> By default, for all methods that return value, mock returns null, an
+ * empty collection or appropriate primitive/primitive wrapper value (e.g: 0,
+ * false, ... for int/Integer, boolean/Boolean, ...). </li>
+ *
+ * <li> Stubbing can be overridden: for example common stubbing can go to
+ * fixture setup but the test methods can override it.
+ * Please note that overridding stubbing is a potential code smell that points out too much stubbing</li>
+ *
+ * <li> Once stubbed, the method will always return stubbed value regardless
+ * of how many times it is called. </li>
+ *
+ * <li> Last stubbing is more important - when you stubbed the same method with
+ * the same arguments many times.
+ * Other words: <b>the order of stubbing matters</b> but it is only meaningful rarely,
+ * e.g. when stubbing exactly the same method calls or sometimes when argument matchers are used, etc.</li>
+ *
+ * </ul>
+ *
+ *
+ *
+ * <h3 id="3">3. <a class="meaningful_link" href="#argument_matchers">Argument matchers</a></h3>
+ *
+ * Mockito verifies argument values in natural java style: by using an <code>equals()</code> method.
+ * Sometimes, when extra flexibility is required then you might use argument matchers:
+ *
+ * <pre class="code"><code class="java">
+ * //stubbing using built-in anyInt() argument matcher
+ * when(mockedList.get(anyInt())).thenReturn("element");
+ *
+ * //stubbing using hamcrest (let's say isValid() returns your own hamcrest matcher):
+ * when(mockedList.contains(argThat(isValid()))).thenReturn("element");
+ *
+ * //following prints "element"
+ * System.out.println(mockedList.get(999));
+ *
+ * //<b>you can also verify using an argument matcher</b>
+ * verify(mockedList).get(anyInt());
+ * </code></pre>
+ *
+ * <p>
+ * Argument matchers allow flexible verification or stubbing.
+ * {@link Matchers Click here to see} more built-in matchers
+ * and examples of <b>custom argument matchers / hamcrest matchers</b>.
+ * <p>
+ * For information solely on <b>custom argument matchers</b> check out javadoc for {@link ArgumentMatcher} class.
+ * <p>
+ * Be reasonable with using complicated argument matching.
+ * The natural matching style using <code>equals()</code> with occasional <code>anyX()</code> matchers tend to give clean & simple tests.
+ * Sometimes it's just better to refactor the code to allow <code>equals()</code> matching or even implement <code>equals()</code> method to help out with testing.
+ * <p>
+ * Also, read <a href="#15">section 15</a> or javadoc for {@link ArgumentCaptor} class.
+ * {@link ArgumentCaptor} is a special implementation of an argument matcher that captures argument values for further assertions.
+ * <p>
+ * <b>Warning on argument matchers:</b>
+ * <p>
+ * If you are using argument matchers, <b>all arguments</b> have to be provided
+ * by matchers.
+ * <p>
+ * E.g: (example shows verification but the same applies to stubbing):
+ *
+ * <pre class="code"><code class="java">
+ * verify(mock).someMethod(anyInt(), anyString(), <b>eq("third argument")</b>);
+ * //above is correct - eq() is also an argument matcher
+ *
+ * verify(mock).someMethod(anyInt(), anyString(), <b>"third argument"</b>);
+ * //above is incorrect - exception will be thrown because third argument is given without an argument matcher.
+ * </code></pre>
+ *
+ * <p>
+ * Matcher methods like <code>anyObject()</code>, <code>eq()</code> <b>do not</b> return matchers.
+ * Internally, they record a matcher on a stack and return a dummy value (usually null).
+ * This implementation is due static type safety imposed by java compiler.
+ * The consequence is that you cannot use <code>anyObject()</code>, <code>eq()</code> methods outside of verified/stubbed method.
+ *
+ *
+ *
+ *
+ * <h3 id="4">4. <a class="meaningful_link" href="#exact_verification">Verifying exact number of invocations</a> /
+ * <a class="meaningful_link" href="#at_least_verification">at least x</a> / never</h3>
+ *
+ * <pre class="code"><code class="java">
+ * //using mock
+ * mockedList.add("once");
+ *
+ * mockedList.add("twice");
+ * mockedList.add("twice");
+ *
+ * mockedList.add("three times");
+ * mockedList.add("three times");
+ * mockedList.add("three times");
+ *
+ * //following two verifications work exactly the same - times(1) is used by default
+ * verify(mockedList).add("once");
+ * verify(mockedList, times(1)).add("once");
+ *
+ * //exact number of invocations verification
+ * verify(mockedList, times(2)).add("twice");
+ * verify(mockedList, times(3)).add("three times");
+ *
+ * //verification using never(). never() is an alias to times(0)
+ * verify(mockedList, never()).add("never happened");
+ *
+ * //verification using atLeast()/atMost()
+ * verify(mockedList, atLeastOnce()).add("three times");
+ * verify(mockedList, atLeast(2)).add("five times");
+ * verify(mockedList, atMost(5)).add("three times");
+ *
+ * </code></pre>
+ *
+ * <p>
+ * <b>times(1) is the default.</b> Therefore using times(1) explicitly can be
+ * omitted.
+ *
+ *
+ *
+ *
+ * <h3 id="5">5. <a class="meaningful_link" href="#stubbing_with_exceptions">Stubbing void methods with exceptions</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * doThrow(new RuntimeException()).when(mockedList).clear();
+ *
+ * //following throws RuntimeException:
+ * mockedList.clear();
+ * </code></pre>
+ *
+ * Read more about doThrow|doAnswer family of methods in paragraph 12.
+ * <p>
+ * Initially, {@link Mockito#stubVoid(Object)} was used for stubbing voids.
+ * Currently <code>stubVoid()</code> is deprecated in favor of {@link Mockito#doThrow(Throwable)}.
+ * This is because of improved readability and consistency with the family of {@link Mockito#doAnswer(Answer)} methods.
+ *
+ *
+ *
+ *
+ * <h3 id="6">6. <a class="meaningful_link" href="#in_order_verification">Verification in order</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * // A. Single mock whose methods must be invoked in a particular order
+ * List singleMock = mock(List.class);
+ *
+ * //using a single mock
+ * singleMock.add("was added first");
+ * singleMock.add("was added second");
+ *
+ * //create an inOrder verifier for a single mock
+ * InOrder inOrder = inOrder(singleMock);
+ *
+ * //following will make sure that add is first called with "was added first, then with "was added second"
+ * inOrder.verify(singleMock).add("was added first");
+ * inOrder.verify(singleMock).add("was added second");
+ *
+ * // B. Multiple mocks that must be used in a particular order
+ * List firstMock = mock(List.class);
+ * List secondMock = mock(List.class);
+ *
+ * //using mocks
+ * firstMock.add("was called first");
+ * secondMock.add("was called second");
+ *
+ * //create inOrder object passing any mocks that need to be verified in order
+ * InOrder inOrder = inOrder(firstMock, secondMock);
+ *
+ * //following will make sure that firstMock was called before secondMock
+ * inOrder.verify(firstMock).add("was called first");
+ * inOrder.verify(secondMock).add("was called second");
+ *
+ * // Oh, and A + B can be mixed together at will
+ * </code></pre>
+ *
+ * Verification in order is flexible - <b>you don't have to verify all
+ * interactions</b> one-by-one but only those that you are interested in
+ * testing in order.
+ * <p>
+ * Also, you can create InOrder object passing only mocks that are relevant for
+ * in-order verification.
+ *
+ *
+ *
+ *
+ * <h3 id="7">7. <a class="meaningful_link" href="#never_verification">Making sure interaction(s) never happened on mock</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * //using mocks - only mockOne is interacted
+ * mockOne.add("one");
+ *
+ * //ordinary verification
+ * verify(mockOne).add("one");
+ *
+ * //verify that method was never called on a mock
+ * verify(mockOne, never()).add("two");
+ *
+ * //verify that other mocks were not interacted
+ * verifyZeroInteractions(mockTwo, mockThree);
+ *
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="8">8. <a class="meaningful_link" href="#finding_redundant_invocations">Finding redundant invocations</a></h3>
+ *
+ * <pre class="code"><code class="java">
+ * //using mocks
+ * mockedList.add("one");
+ * mockedList.add("two");
+ *
+ * verify(mockedList).add("one");
+ *
+ * //following verification will fail
+ * verifyNoMoreInteractions(mockedList);
+ * </code></pre>
+ *
+ * A word of <b>warning</b>:
+ * Some users who did a lot of classic, expect-run-verify mocking tend to use <code>verifyNoMoreInteractions()</code> very often, even in every test method.
+ * <code>verifyNoMoreInteractions()</code> is not recommended to use in every test method.
+ * <code>verifyNoMoreInteractions()</code> is a handy assertion from the interaction testing toolkit. Use it only when it's relevant.
+ * Abusing it leads to <strong>overspecified</strong>, <strong>less maintainable</strong> tests. You can find further reading
+ * <a href="http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/">here</a>.
+ *
+ * <p>
+ * See also {@link Mockito#never()} - it is more explicit and
+ * communicates the intent well.
+ * <p>
+ *
+ *
+ *
+ *
+ * <h3 id="9">9. <a class="meaningful_link" href="#mock_annotation">Shorthand for mocks creation - <code>@Mock</code> annotation</a></h3>
+ *
+ * <ul>
+ * <li>Minimizes repetitive mock creation code.</li>
+ * <li>Makes the test class more readable.</li>
+ * <li>Makes the verification error easier to read because the <b>field name</b>
+ * is used to identify the mock.</li>
+ * </ul>
+ *
+ * <pre class="code"><code class="java">
+ * public class ArticleManagerTest {
+ *
+ * @Mock private ArticleCalculator calculator;
+ * @Mock private ArticleDatabase database;
+ * @Mock private UserProvider userProvider;
+ *
+ * private ArticleManager manager;
+ * </code></pre>
+ *
+ * <b>Important!</b> This needs to be somewhere in the base class or a test
+ * runner:
+ *
+ * <pre class="code"><code class="java">
+ * MockitoAnnotations.initMocks(testClass);
+ * </code></pre>
+ *
+ * You can use built-in runner: {@link MockitoJUnitRunner}.
+ * <p>
+ * Read more here: {@link MockitoAnnotations}
+ *
+ *
+ *
+ *
+ * <h3 id="10">10. <a class="meaningful_link" href="#stubbing_consecutive_calls">Stubbing consecutive calls</a> (iterator-style stubbing)</h3>
+ *
+ * Sometimes we need to stub with different return value/exception for the same
+ * method call. Typical use case could be mocking iterators.
+ * Original version of Mockito did not have this feature to promote simple mocking.
+ * For example, instead of iterators one could use {@link Iterable} or simply
+ * collections. Those offer natural ways of stubbing (e.g. using real
+ * collections). In rare scenarios stubbing consecutive calls could be useful,
+ * though:
+ * <p>
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod("some arg"))
+ * .thenThrow(new RuntimeException())
+ * .thenReturn("foo");
+ *
+ * //First call: throws runtime exception:
+ * mock.someMethod("some arg");
+ *
+ * //Second call: prints "foo"
+ * System.out.println(mock.someMethod("some arg"));
+ *
+ * //Any consecutive call: prints "foo" as well (last stubbing wins).
+ * System.out.println(mock.someMethod("some arg"));
+ * </code></pre>
+ *
+ * Alternative, shorter version of consecutive stubbing:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod("some arg"))
+ * .thenReturn("one", "two", "three");
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="11">11. <a class="meaningful_link" href="#answer_stubs">Stubbing with callbacks</a></h3>
+ *
+ * Allows stubbing with generic {@link Answer} interface.
+ * <p>
+ * Yet another controversial feature which was not included in Mockito
+ * originally. We recommend using simple stubbing with <code>thenReturn()</code> or
+ * <code>thenThrow()</code> only. Those two should be <b>just enough</b> to test/test-drive
+ * any clean & simple code.
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).thenAnswer(new Answer() {
+ * Object answer(InvocationOnMock invocation) {
+ * Object[] args = invocation.getArguments();
+ * Object mock = invocation.getMock();
+ * return "called with arguments: " + args;
+ * }
+ * });
+ *
+ * //Following prints "called with arguments: foo"
+ * System.out.println(mock.someMethod("foo"));
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="12">12. <a class="meaningful_link" href="#do_family_methods_stubs"><code>doReturn()</code>|<code>doThrow()</code>|
+ * <code>doAnswer()</code>|<code>doNothing()</code>|<code>doCallRealMethod()</code> family of methods</a></h3>
+ *
+ * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not
+ * like void methods inside brackets...
+ * <p>
+ * {@link Mockito#doThrow(Throwable)} replaces the {@link Mockito#stubVoid(Object)} method for stubbing voids.
+ * The main reason is improved readability and consistency with the family of <code>doAnswer()</code> methods.
+ * <p>
+ * Use <code>doThrow()</code> when you want to stub a void method with an exception:
+ * <pre class="code"><code class="java">
+ * doThrow(new RuntimeException()).when(mockedList).clear();
+ *
+ * //following throws RuntimeException:
+ * mockedList.clear();
+ * </code></pre>
+ *
+ * <p>
+ * You can use <code>doThrow()</code>, <code>doAnswer()</code>, <code>doNothing()</code>, <code>doReturn()</code>
+ * and <code>doCallRealMethod()</code> in place of the corresponding call with <code>when()</code>, for any method.
+ * It is necessary when you
+ * <ul>
+ * <li>stub void methods</li>
+ * <li>stub methods on spy objects (see below)</li>
+ * <li>stub the same method more than once, to change the behaviour of a mock in the middle of a test.</li>
+ * </ul>
+ * but you may prefer to use these methods in place of the alternative with <code>when()</code>, for all of your stubbing calls.
+ * <p>
+ * Read more about these methods:
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doThrow(Class)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doCallRealMethod()}
+ *
+ *
+ *
+ *
+ * <h3 id="13">13. <a class="meaningful_link" href="#spy">Spying on real objects</a></h3>
+ *
+ * You can create spies of real objects. When you use the spy then the <b>real</b> methods are called
+ * (unless a method was stubbed).
+ * <p>
+ * Real spies should be used <b>carefully and occasionally</b>, for example when dealing with legacy code.
+ *
+ * <p>
+ * Spying on real objects can be associated with "partial mocking" concept.
+ * <b>Before the release 1.8</b>, Mockito spies were not real partial mocks.
+ * The reason was we thought partial mock is a code smell.
+ * At some point we found legitimate use cases for partial mocks
+ * (3rd party interfaces, interim refactoring of legacy code, the full article is <a href=
+ * "http://monkeyisland.pl/2009/01/13/subclass-and-override-vs-partial-mocking-vs-refactoring"
+ * >here</a>)
+ * <p>
+ *
+ * <pre class="code"><code class="java">
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //optionally, you can stub out some methods:
+ * when(spy.size()).thenReturn(100);
+ *
+ * //using the spy calls <b>*real*</b> methods
+ * spy.add("one");
+ * spy.add("two");
+ *
+ * //prints "one" - the first element of a list
+ * System.out.println(spy.get(0));
+ *
+ * //size() method was stubbed - 100 is printed
+ * System.out.println(spy.size());
+ *
+ * //optionally, you can verify
+ * verify(spy).add("one");
+ * verify(spy).add("two");
+ * </code></pre>
+ *
+ * <h4>Important gotcha on spying real objects!</h4>
+ * <ol>
+ * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.
+ * Therefore when using spies please consider <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code> family of
+ * methods for stubbing. Example:
+ *
+ * <pre class="code"><code class="java">
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ * when(spy.get(0)).thenReturn("foo");
+ *
+ * //You have to use doReturn() for stubbing
+ * doReturn("foo").when(spy).get(0);
+ * </code></pre>
+ * </li>
+ *
+ * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.
+ * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction
+ * and their effect on real instance state.
+ * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,
+ * you won't see any effects on the real instance.
+ * </li>
+ *
+ * <li>Watch out for final methods.
+ * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.
+ * Also you won't be able to verify those method as well.
+ * </li>
+ * </ol>
+ *
+ *
+ *
+ *
+ * <h3 id="14">14. Changing <a class="meaningful_link" href="#defaultreturn">default return values of unstubbed invocations</a> (Since 1.7)</h3>
+ *
+ * You can create a mock with specified strategy for its return values.
+ * It's quite advanced feature and typically you don't need it to write decent tests.
+ * However, it can be helpful for working with <b>legacy systems</b>.
+ * <p>
+ * It is the default answer so it will be used <b>only when you don't</b> stub the method call.
+ *
+ * <pre class="code"><code class="java">
+ * Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
+ * Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
+ * </code></pre>
+ *
+ * <p>
+ * Read more about this interesting implementation of <i>Answer</i>: {@link Mockito#RETURNS_SMART_NULLS}
+ *
+ *
+ *
+ *
+ * <h3 id="15">15. <a class="meaningful_link" href="#captors">Capturing arguments</a> for further assertions (Since 1.8.0)</h3>
+ *
+ * Mockito verifies argument values in natural java style: by using an <code>equals()</code> method.
+ * This is also the recommended way of matching arguments because it makes tests clean & simple.
+ * In some situations though, it is helpful to assert on certain arguments after the actual verification.
+ * For example:
+ * <pre class="code"><code class="java">
+ * ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
+ * verify(mock).doSomething(argument.capture());
+ * assertEquals("John", argument.getValue().getName());
+ * </code></pre>
+ *
+ * <b>Warning:</b> it is recommended to use ArgumentCaptor with verification <b>but not</b> with stubbing.
+ * Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.
+ * Also it may reduce defect localization because if stubbed method was not called then no argument is captured.
+ * <p>
+ * In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).
+ * Both techniques can be used for making sure certain arguments where passed to mocks.
+ * However, ArgumentCaptor may be a better fit if:
+ * <ul>
+ * <li>custom argument matcher is not likely to be reused</li>
+ * <li>you just need it to assert on argument values to complete verification</li>
+ * </ul>
+ * Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing.
+ *
+ *
+ *
+ *
+ * <h3 id="16">16. <a class="meaningful_link" href="#partial_mocks">Real partial mocks</a> (Since 1.8.0)</h3>
+ *
+ * Finally, after many internal debates & discussions on the mailing list, partial mock support was added to Mockito.
+ * Previously we considered partial mocks as code smells. However, we found a legitimate use case for partial mocks - more reading:
+ * <a href="http://monkeyisland.pl/2009/01/13/subclass-and-override-vs-partial-mocking-vs-refactoring">here</a>
+ * <p>
+ * <b>Before release 1.8</b> <code>spy()</code> was not producing real partial mocks and it was confusing for some users.
+ * Read more about spying: <a href="#13">here</a> or in javadoc for {@link Mockito#spy(Object)} method.
+ * <p>
+ * <pre class="code"><code class="java">
+ * //you can create partial mock with spy() method:
+ * List list = spy(new LinkedList());
+ *
+ * //you can enable partial mock capabilities selectively on mocks:
+ * Foo mock = mock(Foo.class);
+ * //Be sure the real implementation is 'safe'.
+ * //If real implementation throws exceptions or depends on specific state of the object then you're in trouble.
+ * when(mock.someMethod()).thenCallRealMethod();
+ * </code></pre>
+ *
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ *
+ *
+ *
+ *
+ * <h3 id="17">17. <a class="meaningful_link" href="#resetting_mocks">Resetting mocks</a> (Since 1.8.0)</h3>
+ *
+ * Smart Mockito users hardly use this feature because they know it could be a sign of poor tests.
+ * Normally, you don't need to reset your mocks, just create new mocks for each test method.
+ * <p>
+ * Instead of <code>reset()</code> please consider writing simple, small and focused test methods over lengthy, over-specified tests.
+ * <b>First potential code smell is <code>reset()</code> in the middle of the test method.</b> This probably means you're testing too much.
+ * Follow the whisper of your test methods: "Please keep us small & focused on single behavior".
+ * There are several threads about it on mockito mailing list.
+ * <p>
+ * The only reason we added <code>reset()</code> method is to
+ * make it possible to work with container-injected mocks.
+ * See issue 55 (<a href="http://code.google.com/p/mockito/issues/detail?id=55">here</a>)
+ * or FAQ (<a href="http://code.google.com/p/mockito/wiki/FAQ">here</a>).
+ * <p>
+ * <b>Don't harm yourself.</b> <code>reset()</code> in the middle of the test method is a code smell (you're probably testing too much).
+ * <pre class="code"><code class="java">
+ * List mock = mock(List.class);
+ * when(mock.size()).thenReturn(10);
+ * mock.add(1);
+ *
+ * reset(mock);
+ * //at this point the mock forgot any interactions & stubbing
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="18">18. <a class="meaningful_link" href="#framework_validation">Troubleshooting & validating framework usage</a> (Since 1.8.0)</h3>
+ *
+ * First of all, in case of any trouble, I encourage you to read the Mockito FAQ:
+ * <a href="http://code.google.com/p/mockito/wiki/FAQ">http://code.google.com/p/mockito/wiki/FAQ</a>
+ * <p>
+ * In case of questions you may also post to mockito mailing list:
+ * <a href="http://groups.google.com/group/mockito">http://groups.google.com/group/mockito</a>
+ * <p>
+ * Next, you should know that Mockito validates if you use it correctly <b>all the time</b>.
+ * However, there's a gotcha so please read the javadoc for {@link Mockito#validateMockitoUsage()}
+ *
+ *
+ *
+ *
+ * <h3 id="19">19. <a class="meaningful_link" href="#bdd_mockito">Aliases for behavior driven development</a> (Since 1.8.0)</h3>
+ *
+ * Behavior Driven Development style of writing tests uses <b>//given //when //then</b> comments as fundamental parts of your test methods.
+ * This is exactly how we write our tests and we warmly encourage you to do so!
+ * <p>
+ * Start learning about BDD here: <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">http://en.wikipedia.org/wiki/Behavior_Driven_Development</a>
+ * <p>
+ * The problem is that current stubbing api with canonical role of <b>when</b> word does not integrate nicely with <b>//given //when //then</b> comments.
+ * It's because stubbing belongs to <b>given</b> component of the test and not to the <b>when</b> component of the test.
+ * Hence {@link BDDMockito} class introduces an alias so that you stub method calls with {@link BDDMockito#given(Object)} method.
+ * Now it really nicely integrates with the <b>given</b> component of a BDD style test!
+ * <p>
+ * Here is how the test might look like:
+ * <pre class="code"><code class="java">
+ * import static org.mockito.BDDMockito.*;
+ *
+ * Seller seller = mock(Seller.class);
+ * Shop shop = new Shop(seller);
+ *
+ * public void shouldBuyBread() throws Exception {
+ * //given
+ * given(seller.askForBread()).willReturn(new Bread());
+ *
+ * //when
+ * Goods goods = shop.buyBread();
+ *
+ * //then
+ * assertThat(goods, containBread());
+ * }
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="20">20. <a class="meaningful_link" href="#serializable_mocks">Serializable mocks</a> (Since 1.8.1)</h3>
+ *
+ * Mocks can be made serializable. With this feature you can use a mock in a place that requires dependencies to be serializable.
+ * <p>
+ * WARNING: This should be rarely used in unit testing.
+ * <p>
+ * The behaviour was implemented for a specific use case of a BDD spec that had an unreliable external dependency. This
+ * was in a web environment and the objects from the external dependency were being serialized to pass between layers.
+ * <p>
+ * To create serializable mock use {@link MockSettings#serializable()}:
+ * <pre class="code"><code class="java">
+ * List serializableMock = mock(List.class, withSettings().serializable());
+ * </code></pre>
+ * <p>
+ * The mock can be serialized assuming all the normal <a href='http://java.sun.com/j2se/1.5.0/docs/api/java/io/Serializable.html'>
+ * serialization requirements</a> are met by the class.
+ * <p>
+ * Making a real object spy serializable is a bit more effort as the spy(...) method does not have an overloaded version
+ * which accepts MockSettings. No worries, you will hardly ever use it.
+ *
+ * <pre class="code"><code class="java">
+ * List<Object> list = new ArrayList<Object>();
+ * List<Object> spy = mock(ArrayList.class, withSettings()
+ * .spiedInstance(list)
+ * .defaultAnswer(CALLS_REAL_METHODS)
+ * .serializable());
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="21">21. New annotations: <a class="meaningful_link" href="#captor_annotation"><code>@Captor</code></a>,
+ * <a class="meaningful_link" href="#spy_annotation"><code>@Spy</code></a>,
+ * <a class="meaningful_link" href="#injectmocks_annotation"><code>@InjectMocks</code></a> (Since 1.8.3)</h3>
+ *
+ * <p>
+ * Release 1.8.3 brings new annotations that may be helpful on occasion:
+ *
+ * <ul>
+ * <li>@{@link Captor} simplifies creation of {@link ArgumentCaptor}
+ * - useful when the argument to capture is a nasty generic class and you want to avoid compiler warnings
+ * <li>@{@link Spy} - you can use it instead {@link Mockito#spy(Object)}.
+ * <li>@{@link InjectMocks} - injects mock or spy fields into tested object automatically.
+ * </ul>
+ *
+ * <p>
+ * Note that @{@link InjectMocks} can only be used in combination with the @{@link Spy} annotation, it means
+ * that Mockito will inject mocks in a partial mock under testing. As a remainder, please read point 16 about partial mocks.
+ *
+ * <p>
+ * All new annotations are <b>*only*</b> processed on {@link MockitoAnnotations#initMocks(Object)}.
+ * Just like for @{@link Mock} annotation you can use the built-in runner: {@link MockitoJUnitRunner}.
+ * <p>
+ *
+ *
+ *
+ *
+ * <h3 id="22">22. <a class="meaningful_link" href="#verification_timeout">Verification with timeout</a> (Since 1.8.5)</h3>
+ * <p>
+ * Allows verifying with timeout. It causes a verify to wait for a specified period of time for a desired
+ * interaction rather than fails immediately if had not already happened. May be useful for testing in concurrent
+ * conditions.
+ * <p>
+ * It feels this feature should be used rarely - figure out a better way of testing your multi-threaded system.
+ * <p>
+ * Not yet implemented to work with InOrder verification.
+ * <p>
+ * Examples:
+ * <p>
+ * <pre class="code"><code class="java">
+ * //passes when someMethod() is called within given time span
+ * verify(mock, timeout(100)).someMethod();
+ * //above is an alias to:
+ * verify(mock, timeout(100).times(1)).someMethod();
+ *
+ * //passes when someMethod() is called <b>*exactly*</b> 2 times within given time span
+ * verify(mock, timeout(100).times(2)).someMethod();
+ *
+ * //passes when someMethod() is called <b>*at least*</b> 2 times within given time span
+ * verify(mock, timeout(100).atLeast(2)).someMethod();
+ *
+ * //verifies someMethod() within given time span using given verification mode
+ * //useful only if you have your own custom verification modes.
+ * verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="23">23. (New) <a class="meaningful_link" href="#automatic_instantiation">Automatic instantiation of <code>@Spies</code>,
+ * <code>@InjectMocks</code></a> and <a class="meaningful_link" href="#constructor_injection">constructor injection goodness</a> (Since 1.9.0)</h3>
+ *
+ * <p>
+ * Mockito will now try to instantiate @{@link Spy} and will instantiate @{@link InjectMocks} fields
+ * using <b>constructor</b> injection, <b>setter</b> injection, or <b>field</b> injection.
+ * <p>
+ * To take advantage of this feature you need to use {@link MockitoAnnotations#initMocks(Object)} or {@link MockitoJUnitRunner}.
+ * <p>
+ * Read more about available tricks and the rules of injection in the javadoc for {@link InjectMocks}
+ * <pre class="code"><code class="java">
+ * //instead:
+ * @Spy BeerDrinker drinker = new BeerDrinker();
+ * //you can write:
+ * @Spy BeerDrinker drinker;
+ *
+ * //same applies to @InjectMocks annotation:
+ * @InjectMocks LocalPub;
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="24">24. (New) <a class="meaningful_link" href="#one_liner_stub">One-liner stubs</a> (Since 1.9.0)</h3>
+ * <p>
+ * Mockito will now allow you to create mocks when stubbing.
+ * Basically, it allows to create a stub in one line of code.
+ * This can be helpful to keep test code clean.
+ * For example, some boring stub can be created & stubbed at field initialization in a test:
+ * <pre class="code"><code class="java">
+ * public class CarTest {
+ * Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();
+ *
+ * @Test public void should... {}
+ * </code></pre>
+ *
+ *
+ *
+ *
+ * <h3 id="25">25. (New) <a class="meaningful_link" href="#ignore_stubs_verification">Verification ignoring stubs</a> (Since 1.9.0)</h3>
+ * <p>
+ * Mockito will now allow to ignore stubbing for the sake of verification.
+ * Sometimes useful when coupled with <code>verifyNoMoreInteractions()</code> or verification <code>inOrder()</code>.
+ * Helps avoiding redundant verification of stubbed calls - typically we're not interested in verifying stubs.
+ * <p>
+ * <b>Warning</b>, <code>ignoreStubs()</code> might lead to overuse of verifyNoMoreInteractions(ignoreStubs(...));
+ * Bear in mind that Mockito does not recommend bombarding every test with <code>verifyNoMoreInteractions()</code>
+ * for the reasons outlined in javadoc for {@link Mockito#verifyNoMoreInteractions(Object...)}
+ * <p>Some examples:
+ * <pre class="code"><code class="java">
+ * verify(mock).foo();
+ * verify(mockTwo).bar();
+ *
+ * //ignores all stubbed methods:
+ * verifyNoMoreInvocations(ignoreStubs(mock, mockTwo));
+ *
+ * //creates InOrder that will ignore stubbed
+ * InOrder inOrder = inOrder(ignoreStubs(mock, mockTwo));
+ * inOrder.verify(mock).foo();
+ * inOrder.verify(mockTwo).bar();
+ * inOrder.verifyNoMoreInteractions();
+ * </code></pre>
+ * <p>
+ * Advanced examples and more details can be found in javadoc for {@link Mockito#ignoreStubs(Object...)}
+ *
+ *
+ *
+ *
+ * <h3 id="26">26. (**New**) <a class="meaningful_link" href="#mocking_details">Mocking details</a> (Since 1.9.5)</h3>
+ * <p>
+ * To identify whether a particular object is a mock or a spy:
+ * <pre class="code"><code class="java">
+ * Mockito.mockingDetails(someObject).isMock();
+ * Mockito.mockingDetails(someObject).isSpy();
+ * </code></pre>
+ * Both the {@link MockingDetails#isMock} and {@link MockingDetails#isSpy()} methods return <code>boolean</code>.
+ * As a spy is just a different kind of mock, <code>isMock()</code> returns true if the object is a spy.
+ * In future Mockito versions MockingDetails may grow and provide other useful information about the mock,
+ * e.g. invocations, stubbing info, etc.
+ *
+ *
+ *
+ *
+ * <h3 id="27">27. (**New**) <a class="meaningful_link" href="#delegating_call_to_real_instance">Delegate calls to real instance</a> (Since 1.9.5)</h3>
+ *
+ * <p>Useful for spies or partial mocks of objects <strong>that are difficult to mock or spy</strong> using the usual spy API.
+ * Possible use cases:
+ * <ul>
+ * <li>Final classes but with an interface</li>
+ * <li>Already custom proxied object</li>
+ * <li>Special objects with a finalize method, i.e. to avoid executing it 2 times</li>
+ * </ul>
+ *
+ * <p>The difference with the regular spy:
+ * <ul>
+ * <li>
+ * The regular spy ({@link #spy(Object)}) contains <strong>all</strong> state from the spied instance
+ * and the methods are invoked on the spy. The spied instance is only used at mock creation to copy the state from.
+ * If you call a method on a regular spy and it internally calls other methods on this spy, those calls are remembered
+ * for verifications, and they can be effectively stubbed.
+ * </li>
+ * <li>
+ * The mock that delegates simply delegates all methods to the delegate.
+ * The delegate is used all the time as methods are delegated onto it.
+ * If you call a method on a mock that delegates and it internally calls other methods on this mock,
+ * those calls are <strong>not</strong> remembered for verifications, stubbing does not have effect on them, too.
+ * Mock that delegates is less powerful than the regular spy but it is useful when the regular spy cannot be created.
+ * </li>
+ * </ul>
+ *
+ * <p>
+ * See more information in docs for {@link AdditionalAnswers#delegatesTo(Object)}.
+ *
+ *
+ *
+ *
+ * <h3 id="28">28. (**New**) <a class="meaningful_link" href="#mock_maker_plugin"><code>MockMaker</code> API</a> (Since 1.9.5)</h3>
+ * <p>Driven by requirements and patches from Google Android guys Mockito now offers an extension point
+ * that allows replacing the proxy generation engine. By default, Mockito uses cglib to create dynamic proxies.
+ * <p>The extension point is for advanced users that want to extend Mockito. For example, it is now possible
+ * to use Mockito for Android testing with a help of dexmaker.
+ * <p>For more details, motivations and examples please refer to
+ * the docs for {@link org.mockito.plugins.MockMaker}.
+ *
+ */
+@SuppressWarnings("unchecked")
+public class Mockito extends Matchers {
+
+ static final MockitoCore MOCKITO_CORE = new MockitoCore();
+
+ /**
+ * The default <code>Answer</code> of every mock <b>if</b> the mock was not stubbed.
+ * Typically it just returns some empty value.
+ * <p>
+ * {@link Answer} can be used to define the return values of unstubbed invocations.
+ * <p>
+ * This implementation first tries the global configuration.
+ * If there is no global configuration then it uses {@link ReturnsEmptyValues} (returns zeros, empty collections, nulls, etc.)
+ */
+ public static final Answer<Object> RETURNS_DEFAULTS = Answers.RETURNS_DEFAULTS.get();
+
+ /**
+ * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}.
+ * <p>
+ * {@link Answer} can be used to define the return values of unstubbed invocations.
+ * <p>
+ * This implementation can be helpful when working with legacy code.
+ * Unstubbed methods often return null. If your code uses the object returned by an unstubbed call you get a NullPointerException.
+ * This implementation of Answer <b>returns SmartNull instead of null</b>.
+ * <code>SmartNull</code> gives nicer exception message than NPE because it points out the line where unstubbed method was called. You just click on the stack trace.
+ * <p>
+ * <code>ReturnsSmartNulls</code> first tries to return ordinary return values (see {@link ReturnsMoreEmptyValues})
+ * then it tries to return SmartNull. If the return type is final then plain null is returned.
+ * <p>
+ * <code>ReturnsSmartNulls</code> will be probably the default return values strategy in Mockito 2.0.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * Foo mock = (Foo.class, RETURNS_SMART_NULLS);
+ *
+ * //calling unstubbed method here:
+ * Stuff stuff = mock.getStuff();
+ *
+ * //using object returned by unstubbed call:
+ * stuff.doSomething();
+ *
+ * //Above doesn't yield NullPointerException this time!
+ * //Instead, SmartNullPointerException is thrown.
+ * //Exception's cause links to unstubbed <i>mock.getStuff()</i> - just click on the stack trace.
+ * </code></pre>
+ */
+ public static final Answer<Object> RETURNS_SMART_NULLS = Answers.RETURNS_SMART_NULLS.get();
+
+ /**
+ * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}
+ * <p>
+ * {@link Answer} can be used to define the return values of unstubbed invocations.
+ * <p>
+ * This implementation can be helpful when working with legacy code.
+ * <p>
+ * ReturnsMocks first tries to return ordinary return values (see {@link ReturnsMoreEmptyValues})
+ * then it tries to return mocks. If the return type cannot be mocked (e.g. is final) then plain null is returned.
+ * <p>
+ */
+ public static final Answer<Object> RETURNS_MOCKS = Answers.RETURNS_MOCKS.get();
+
+ /**
+ * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}.
+ * <p>
+ * Example that shows how deep stub works:
+ * <pre class="code"><code class="java">
+ * Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
+ *
+ * // note that we're stubbing a chain of methods here: getBar().getName()
+ * when(mock.getBar().getName()).thenReturn("deep");
+ *
+ * // note that we're chaining method calls: getBar().getName()
+ * assertEquals("deep", mock.getBar().getName());
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * <strong>WARNING: </strong>
+ * This feature should rarely be required for regular clean code! Leave it for legacy code.
+ * Mocking a mock to return a mock, to return a mock, (...), to return something meaningful
+ * hints at violation of Law of Demeter or mocking a value object (a well known anti-pattern).
+ * </p>
+ *
+ * <p>
+ * Good quote I've seen one day on the web: <strong>every time a mock returns a mock a fairy dies</strong>.
+ * </p>
+ *
+ * <p>
+ * Please note that this answer will return existing mocks that matches the stub. This
+ * behavior is ok with deep stubs and allows verification to work on the last mock of the chain.
+ * <pre class="code"><code class="java">
+ * when(mock.getBar(anyString()).getThingy().getName()).thenReturn("deep");
+ *
+ * mock.getBar("candy bar").getThingy().getName();
+ *
+ * assertSame(mock.getBar(anyString()).getThingy().getName(), mock.getBar(anyString()).getThingy().getName());
+ * verify(mock.getBar("candy bar").getThingy()).getName();
+ * verify(mock.getBar(anyString()).getThingy()).getName();
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * Verification only works with the last mock in the chain. You can use verification modes.
+ * <pre class="code"><code class="java">
+ * when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
+ * when(person.getAddress(anyString()).getStreet(Locale.ITALIAN).getName()).thenReturn("deep");
+ * when(person.getAddress(anyString()).getStreet(Locale.CHINESE).getName()).thenReturn("deep");
+ *
+ * person.getAddress("the docks").getStreet().getName();
+ * person.getAddress("the docks").getStreet().getLongName();
+ * person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();
+ * person.getAddress("the docks").getStreet(Locale.CHINESE).getName();
+ *
+ * // note that we are actually referring to the very last mock in the stubbing chain.
+ * InOrder inOrder = inOrder(
+ * person.getAddress("the docks").getStreet(),
+ * person.getAddress("the docks").getStreet(Locale.CHINESE),
+ * person.getAddress("the docks").getStreet(Locale.ITALIAN)
+ * );
+ * inOrder.verify(person.getAddress("the docks").getStreet(), times(1)).getName();
+ * inOrder.verify(person.getAddress("the docks").getStreet()).getLongName();
+ * inOrder.verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atLeast(1)).getName();
+ * inOrder.verify(person.getAddress("the docks").getStreet(Locale.CHINESE)).getName();
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * How deep stub work internally?
+ * <pre class="code"><code class="java">
+ * //this:
+ * Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
+ * when(mock.getBar().getName(), "deep");
+ *
+ * //is equivalent of
+ * Foo foo = mock(Foo.class);
+ * Bar bar = mock(Bar.class);
+ * when(foo.getBar()).thenReturn(bar);
+ * when(bar.getName()).thenReturn("deep");
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * This feature will not work when any return type of methods included in the chain cannot be mocked
+ * (for example: is a primitive or a final class). This is because of java type system.
+ * </p>
+ */
+ public static final Answer<Object> RETURNS_DEEP_STUBS = Answers.RETURNS_DEEP_STUBS.get();
+
+ /**
+ * Optional <code>Answer</code> to be used with {@link Mockito#mock(Class, Answer)}
+ * <p>
+ * {@link Answer} can be used to define the return values of unstubbed invocations.
+ * <p>
+ * This implementation can be helpful when working with legacy code.
+ * When this implementation is used, unstubbed methods will delegate to the real implementation.
+ * This is a way to create a partial mock object that calls real methods by default.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * Foo mock = mock(Foo.class, CALLS_REAL_METHODS);
+ *
+ * // this calls the real implementation of Foo.getSomething()
+ * value = mock.getSomething();
+ *
+ * when(mock.getSomething()).thenReturn(fakeValue);
+ *
+ * // now fakeValue is returned
+ * value = mock.getSomething();
+ * </code></pre>
+ */
+ public static final Answer<Object> CALLS_REAL_METHODS = Answers.CALLS_REAL_METHODS.get();
+
+ /**
+ * Creates mock object of given class or interface.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param classToMock class or interface to mock
+ * @return mock object
+ */
+ public static <T> T mock(Class<T> classToMock) {
+ return mock(classToMock, withSettings().defaultAnswer(RETURNS_DEFAULTS));
+ }
+
+ /**
+ * Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors.
+ * <p>
+ * Beware that naming mocks is not a solution for complex code which uses too many mocks or collaborators.
+ * <b>If you have too many mocks then refactor the code</b> so that it's easy to test/debug without necessity of naming mocks.
+ * <p>
+ * <b>If you use <code>@Mock</code> annotation then you've got naming mocks for free!</b> <code>@Mock</code> uses field name as mock name. {@link Mock Read more.}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param classToMock class or interface to mock
+ * @param name of the mock
+ * @return mock object
+ */
+ public static <T> T mock(Class<T> classToMock, String name) {
+ return mock(classToMock, withSettings()
+ .name(name)
+ .defaultAnswer(RETURNS_DEFAULTS));
+ }
+
+ /**
+ * Returns a MockingDetails instance that enables inspecting a particular object for Mockito related information.
+ * Can be used to find out if given object is a Mockito mock
+ * or to find out if a given mock is a spy or mock.
+ * <p>
+ * In future Mockito versions MockingDetails may grow and provide other useful information about the mock,
+ * e.g. invocations, stubbing info, etc.
+ *
+ * @param toInspect - object to inspect
+ * @return A {@link org.mockito.MockingDetails} instance.
+ * @since 1.9.5
+ */
+ @Incubating
+ public static MockingDetails mockingDetails(Object toInspect) {
+ return MOCKITO_CORE.mockingDetails(toInspect);
+ }
+
+ /**
+ * <b>Deprecated : Please use mock(Foo.class, defaultAnswer);</b>
+ * <p>
+ * See {@link Mockito#mock(Class, Answer)}
+ * <p>
+ * Why it is deprecated? ReturnValues is being replaced by Answer
+ * for better consistency & interoperability of the framework.
+ * Answer interface has been in Mockito for a while and it has the same responsibility as ReturnValues.
+ * There's no point in mainting exactly the same interfaces.
+ * <p>
+ * Creates mock with a specified strategy for its return values.
+ * It's quite advanced feature and typically you don't need it to write decent tests.
+ * However it can be helpful when working with legacy systems.
+ * <p>
+ * Obviously return values are used only when you don't stub the method call.
+ *
+ * <pre class="code"><code class="java">
+ * Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
+ * Foo mockTwo = mock(Foo.class, new YourOwnReturnValues());
+ * </code></pre>
+ *
+ * <p>See examples in javadoc for {@link Mockito} class</p>
+ *
+ * @param classToMock class or interface to mock
+ * @param returnValues default return values for unstubbed methods
+ *
+ * @return mock object
+ *
+ * @deprecated <b>Please use mock(Foo.class, defaultAnswer);</b>
+ */
+ @Deprecated
+ public static <T> T mock(Class<T> classToMock, ReturnValues returnValues) {
+ return mock(classToMock, withSettings().defaultAnswer(new AnswerReturnValuesAdapter(returnValues)));
+ }
+
+ /**
+ * Creates mock with a specified strategy for its answers to interactions.
+ * It's quite advanced feature and typically you don't need it to write decent tests.
+ * However it can be helpful when working with legacy systems.
+ * <p>
+ * It is the default answer so it will be used <b>only when you don't</b> stub the method call.
+ *
+ * <pre class="code"><code class="java">
+ * Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);
+ * Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
+ * </code></pre>
+ *
+ * <p>See examples in javadoc for {@link Mockito} class</p>
+ *
+ * @param classToMock class or interface to mock
+ * @param defaultAnswer default answer for unstubbed methods
+ *
+ * @return mock object
+ */
+ public static <T> T mock(Class<T> classToMock, Answer defaultAnswer) {
+ return mock(classToMock, withSettings().defaultAnswer(defaultAnswer));
+ }
+
+ /**
+ * Creates a mock with some non-standard settings.
+ * <p>
+ * The number of configuration points for a mock grows
+ * so we need a fluent way to introduce new configuration without adding more and more overloaded Mockito.mock() methods.
+ * Hence {@link MockSettings}.
+ * <pre class="code"><code class="java">
+ * Listener mock = mock(Listener.class, withSettings()
+ * .name("firstListner").defaultBehavior(RETURNS_SMART_NULLS));
+ * );
+ * </code></pre>
+ * <b>Use it carefully and occasionally</b>. What might be reason your test needs non-standard mocks?
+ * Is the code under test so complicated that it requires non-standard mocks?
+ * Wouldn't you prefer to refactor the code under test so it is testable in a simple way?
+ * <p>
+ * See also {@link Mockito#withSettings()}
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param classToMock class or interface to mock
+ * @param mockSettings additional mock settings
+ * @return mock object
+ */
+ public static <T> T mock(Class<T> classToMock, MockSettings mockSettings) {
+ return MOCKITO_CORE.mock(classToMock, mockSettings);
+ }
+
+ /**
+ * Creates a spy of the real object. The spy calls <b>real</b> methods unless they are stubbed.
+ * <p>
+ * Real spies should be used <b>carefully and occasionally</b>, for example when dealing with legacy code.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ * <p>
+ * Example:
+ *
+ * <pre class="code"><code class="java">
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //optionally, you can stub out some methods:
+ * when(spy.size()).thenReturn(100);
+ *
+ * //using the spy calls <b>real</b> methods
+ * spy.add("one");
+ * spy.add("two");
+ *
+ * //prints "one" - the first element of a list
+ * System.out.println(spy.get(0));
+ *
+ * //size() method was stubbed - 100 is printed
+ * System.out.println(spy.size());
+ *
+ * //optionally, you can verify
+ * verify(spy).add("one");
+ * verify(spy).add("two");
+ * </code></pre>
+ *
+ * <h4>Important gotcha on spying real objects!</h4>
+ * <ol>
+ * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.
+ * Therefore for spies it is recommended to always use <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code>|<code>CallRealMethod</code>
+ * family of methods for stubbing. Example:
+ *
+ * <pre class="code"><code class="java">
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ * when(spy.get(0)).thenReturn("foo");
+ *
+ * //You have to use doReturn() for stubbing
+ * doReturn("foo").when(spy).get(0);
+ * </code></pre>
+ * </li>
+ *
+ * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.
+ * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction
+ * and their effect on real instance state.
+ * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,
+ * you won't see any effects on the real instance.</li>
+ *
+ * <li>Watch out for final methods.
+ * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.
+ * Also you won't be able to verify those method as well.
+ * </li>
+ * </ol>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param object
+ * to spy on
+ * @return a spy of the real object
+ */
+ public static <T> T spy(T object) {
+ return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
+ .spiedInstance(object)
+ .defaultAnswer(CALLS_REAL_METHODS));
+ }
+
+ /**
+ * Stubs a method call with return value or an exception. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * stub(mock.someMethod()).toReturn(10);
+ *
+ * //you can use flexible argument matchers, e.g:
+ * stub(mock.someMethod(<b>anyString()</b>)).toReturn(10);
+ *
+ * //setting exception to be thrown:
+ * stub(mock.someMethod("some arg")).toThrow(new RuntimeException());
+ *
+ * //you can stub with different behavior for consecutive method calls.
+ * //Last stubbing (e.g: toReturn("foo")) determines the behavior for further consecutive calls.
+ * stub(mock.someMethod("some arg"))
+ * .toThrow(new RuntimeException())
+ * .toReturn("foo");
+ * </code></pre>
+ * <p>
+ * Some users find stub() confusing therefore {@link Mockito#when(Object)} is recommended over stub()
+ * <pre class="code"><code class="java">
+ * //Instead of:
+ * stub(mock.count()).toReturn(10);
+ *
+ * //You can do:
+ * when(mock.count()).thenReturn(10);
+ * </code></pre>
+ * For stubbing void methods with throwables see: {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * Stubbing can be overridden: for example common stubbing can go to fixture
+ * setup but the test methods can override it.
+ * Please note that overridding stubbing is a potential code smell that points out too much stubbing.
+ * <p>
+ * Once stubbed, the method will always return stubbed value regardless
+ * of how many times it is called.
+ * <p>
+ * Last stubbing is more important - when you stubbed the same method with
+ * the same arguments many times.
+ * <p>
+ * Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>.
+ * Let's say you've stubbed foo.bar().
+ * If your code cares what foo.bar() returns then something else breaks(often before even verify() gets executed).
+ * If your code doesn't care what get(0) returns then it should not be stubbed.
+ * Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.
+ *
+ * @param methodCall
+ * method call
+ * @return DeprecatedOngoingStubbing object to set stubbed value/exception
+ */
+ public static <T> DeprecatedOngoingStubbing<T> stub(T methodCall) {
+ return MOCKITO_CORE.stub(methodCall);
+ }
+
+ /**
+ * Enables stubbing methods. Use it when you want the mock to return particular value when particular method is called.
+ * <p>
+ * Simply put: "<b>When</b> the x method is called <b>then</b> return y".
+ * <p>
+ * <b>when() is a successor of deprecated {@link Mockito#stub(Object)}</b>
+ * <p>
+ * Examples:
+ *
+ * <pre class="code"><code class="java">
+ * <b>when</b>(mock.someMethod()).<b>thenReturn</b>(10);
+ *
+ * //you can use flexible argument matchers, e.g:
+ * when(mock.someMethod(<b>anyString()</b>)).thenReturn(10);
+ *
+ * //setting exception to be thrown:
+ * when(mock.someMethod("some arg")).thenThrow(new RuntimeException());
+ *
+ * //you can set different behavior for consecutive method calls.
+ * //Last stubbing (e.g: thenReturn("foo")) determines the behavior of further consecutive calls.
+ * when(mock.someMethod("some arg"))
+ * .thenThrow(new RuntimeException())
+ * .thenReturn("foo");
+ *
+ * //Alternative, shorter version for consecutive stubbing:
+ * when(mock.someMethod("some arg"))
+ * .thenReturn("one", "two");
+ * //is the same as:
+ * when(mock.someMethod("some arg"))
+ * .thenReturn("one")
+ * .thenReturn("two");
+ *
+ * //shorter version for consecutive method calls throwing exceptions:
+ * when(mock.someMethod("some arg"))
+ * .thenThrow(new RuntimeException(), new NullPointerException();
+ *
+ * </code></pre>
+ *
+ * For stubbing void methods with throwables see: {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * Stubbing can be overridden: for example common stubbing can go to fixture
+ * setup but the test methods can override it.
+ * Please note that overridding stubbing is a potential code smell that points out too much stubbing.
+ * <p>
+ * Once stubbed, the method will always return stubbed value regardless
+ * of how many times it is called.
+ * <p>
+ * Last stubbing is more important - when you stubbed the same method with
+ * the same arguments many times.
+ * <p>
+ * Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>.
+ * Let's say you've stubbed <code>foo.bar()</code>.
+ * If your code cares what <code>foo.bar()</code> returns then something else breaks(often before even <code>verify()</code> gets executed).
+ * If your code doesn't care what <code>get(0)</code> returns then it should not be stubbed.
+ * Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.
+ *
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ * @param methodCall method to be stubbed
+ * @return OngoingStubbing object used to stub fluently.
+ * <strong>Do not</strong> create a reference to this returned object.
+ */
+ public static <T> OngoingStubbing<T> when(T methodCall) {
+ return MOCKITO_CORE.when(methodCall);
+ }
+
+ /**
+ * Verifies certain behavior <b>happened once</b>.
+ * <p>
+ * Alias to <code>verify(mock, times(1))</code> E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock).someMethod("some arg");
+ * </code></pre>
+ * Above is equivalent to:
+ * <pre class="code"><code class="java">
+ * verify(mock, times(1)).someMethod("some arg");
+ * </code></pre>
+ * <p>
+ * Arguments passed are compared using <code>equals()</code> method.
+ * Read about {@link ArgumentCaptor} or {@link ArgumentMatcher} to find out other ways of matching / asserting arguments passed.
+ * <p>
+ * Although it is possible to verify a stubbed invocation, usually <b>it's just redundant</b>.
+ * Let's say you've stubbed <code>foo.bar()</code>.
+ * If your code cares what <code>foo.bar()</code> returns then something else breaks(often before even <code>verify()</code> gets executed).
+ * If your code doesn't care what <code>get(0)</code> returns then it should not be stubbed.
+ * Not convinced? See <a href="http://monkeyisland.pl/2008/04/26/asking-and-telling">here</a>.
+ *
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mock to be verified
+ * @return mock object itself
+ */
+ public static <T> T verify(T mock) {
+ return MOCKITO_CORE.verify(mock, times(1));
+ }
+
+ /**
+ * Verifies certain behavior happened at least once / exact number of times / never. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, times(5)).someMethod("was called five times");
+ *
+ * verify(mock, atLeast(2)).someMethod("was called at least two times");
+ *
+ * //you can use flexible argument matchers, e.g:
+ * verify(mock, atLeastOnce()).someMethod(<b>anyString()</b>);
+ * </code></pre>
+ *
+ * <b>times(1) is the default</b> and can be omitted
+ * <p>
+ * Arguments passed are compared using <code>equals()</code> method.
+ * Read about {@link ArgumentCaptor} or {@link ArgumentMatcher} to find out other ways of matching / asserting arguments passed.
+ * <p>
+ *
+ * @param mock to be verified
+ * @param mode times(x), atLeastOnce() or never()
+ *
+ * @return mock object itself
+ */
+ public static <T> T verify(T mock, VerificationMode mode) {
+ return MOCKITO_CORE.verify(mock, mode);
+ }
+
+ /**
+ * Smart Mockito users hardly use this feature because they know it could be a sign of poor tests.
+ * Normally, you don't need to reset your mocks, just create new mocks for each test method.
+ * <p>
+ * Instead of <code>#reset()</code> please consider writing simple, small and focused test methods over lengthy, over-specified tests.
+ * <b>First potential code smell is <code>reset()</code> in the middle of the test method.</b> This probably means you're testing too much.
+ * Follow the whisper of your test methods: "Please keep us small & focused on single behavior".
+ * There are several threads about it on mockito mailing list.
+ * <p>
+ * The only reason we added <code>reset()</code> method is to
+ * make it possible to work with container-injected mocks.
+ * See issue 55 (<a href="http://code.google.com/p/mockito/issues/detail?id=55">here</a>)
+ * or FAQ (<a href="http://code.google.com/p/mockito/wiki/FAQ">here</a>).
+ * <p>
+ * <b>Don't harm yourself.</b> <code>reset()</code> in the middle of the test method is a code smell (you're probably testing too much).
+ * <pre class="code"><code class="java">
+ * List mock = mock(List.class);
+ * when(mock.size()).thenReturn(10);
+ * mock.add(1);
+ *
+ * reset(mock);
+ * //at this point the mock forgot any interactions & stubbing
+ * </code></pre>
+ *
+ * @param <T> The Type of the mocks
+ * @param mocks to be reset
+ */
+ public static <T> void reset(T ... mocks) {
+ MOCKITO_CORE.reset(mocks);
+ }
+
+ /**
+ * Checks if any of given mocks has any unverified interaction.
+ * <p>
+ * You can use this method after you verified your mocks - to make sure that nothing
+ * else was invoked on your mocks.
+ * <p>
+ * See also {@link Mockito#never()} - it is more explicit and communicates the intent well.
+ * <p>
+ * Stubbed invocations (if called) are also treated as interactions.
+ * <p>
+ * A word of <b>warning</b>:
+ * Some users who did a lot of classic, expect-run-verify mocking tend to use <code>verifyNoMoreInteractions()</code> very often, even in every test method.
+ * <code>verifyNoMoreInteractions()</code> is not recommended to use in every test method.
+ * <code>verifyNoMoreInteractions()</code> is a handy assertion from the interaction testing toolkit. Use it only when it's relevant.
+ * Abusing it leads to overspecified, less maintainable tests. You can find further reading
+ * <a href="http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/">here</a>.
+ * <p>
+ * This method will also detect unverified invocations that occurred before the test method,
+ * for example: in <code>setUp()</code>, <code>@Before</code> method or in constructor.
+ * Consider writing nice code that makes interactions only in test methods.
+ *
+ * <p>
+ * Example:
+ *
+ * <pre class="code"><code class="java">
+ * //interactions
+ * mock.doSomething();
+ * mock.doSomethingUnexpected();
+ *
+ * //verification
+ * verify(mock).doSomething();
+ *
+ * //following will fail because 'doSomethingUnexpected()' is unexpected
+ * verifyNoMoreInteractions(mock);
+ *
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mocks to be verified
+ */
+ public static void verifyNoMoreInteractions(Object... mocks) {
+ MOCKITO_CORE.verifyNoMoreInteractions(mocks);
+ }
+
+ /**
+ * Verifies that no interactions happened on given mocks.
+ * <pre class="code"><code class="java">
+ * verifyZeroInteractions(mockOne, mockTwo);
+ * </code></pre>
+ * This method will also detect invocations
+ * that occurred before the test method, for example: in <code>setUp()</code>, <code>@Before</code> method or in constructor.
+ * Consider writing nice code that makes interactions only in test methods.
+ * <p>
+ * See also {@link Mockito#never()} - it is more explicit and communicates the intent well.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mocks to be verified
+ */
+ public static void verifyZeroInteractions(Object... mocks) {
+ MOCKITO_CORE.verifyNoMoreInteractions(mocks);
+ }
+
+ /**
+ * <pre class="code"><code class="java">
+ * //Instead of:
+ * stubVoid(mock).toThrow(e).on().someVoidMethod();
+ *
+ * //Please do:
+ * doThrow(e).when(mock).someVoidMethod();
+ * </code></pre>
+ *
+ * doThrow() replaces stubVoid() because of improved readability and consistency with the family of doAnswer() methods.
+ * <p>
+ * Originally, <code>stubVoid()</code> was used for stubbing void methods with exceptions. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * stubVoid(mock).toThrow(new RuntimeException()).on().someMethod();
+ *
+ * //you can stub with different behavior for consecutive calls.
+ * //Last stubbing (e.g. toReturn()) determines the behavior for further consecutive calls.
+ * stubVoid(mock)
+ * .toThrow(new RuntimeException())
+ * .toReturn()
+ * .on().someMethod();
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @deprecated Use {@link Mockito#doThrow(Throwable)} method for stubbing voids
+ *
+ * @param mock
+ * to stub
+ * @return stubbable object that allows stubbing with throwable
+ */
+ public static <T> VoidMethodStubbable<T> stubVoid(T mock) {
+ return MOCKITO_CORE.stubVoid(mock);
+ }
+
+ /**
+ * Use <code>doThrow()</code> when you want to stub the void method with an exception.
+ * <p>
+ * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not like void methods inside brackets...
+ * <p>
+ * Example:
+ *
+ * <pre class="code"><code class="java">
+ * doThrow(new RuntimeException()).when(mock).someVoidMethod();
+ * </code></pre>
+ *
+ * @param toBeThrown to be thrown when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static Stubber doThrow(Throwable toBeThrown) {
+ return MOCKITO_CORE.doAnswer(new ThrowsException(toBeThrown));
+ }
+
+ /**
+ * Use <code>doThrow()</code> when you want to stub the void method to throw exception of specified class.
+ * <p>
+ * A new exception instance will be created for each method invocation.
+ * <p>
+ * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not like void methods inside brackets...
+ * <p>
+ * Example:
+ *
+ * <pre class="code"><code class="java">
+ * doThrow(RuntimeException.class).when(mock).someVoidMethod();
+ * </code></pre>
+ *
+ * @param toBeThrown to be thrown when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ * @since 1.9.0
+ */
+ public static Stubber doThrow(Class<? extends Throwable> toBeThrown) {
+ return MOCKITO_CORE.doAnswer(new ThrowsExceptionClass(toBeThrown));
+ }
+
+
+ /**
+ * Use <code>doCallRealMethod()</code> when you want to call the real implementation of a method.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ * <p>
+ * See also javadoc {@link Mockito#spy(Object)} to find out more about partial mocks.
+ * <b>Mockito.spy() is a recommended way of creating partial mocks.</b>
+ * The reason is it guarantees real methods are called against correctly constructed object because you're responsible for constructing the object passed to spy() method.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * Foo mock = mock(Foo.class);
+ * doCallRealMethod().when(mock).someVoidMethod();
+ *
+ * // this will call the real implementation of Foo.someVoidMethod()
+ * mock.someVoidMethod();
+ * </code></pre>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return stubber - to select a method for stubbing
+ * @since 1.9.5
+ */
+ public static Stubber doCallRealMethod() {
+ return MOCKITO_CORE.doAnswer(new CallsRealMethods());
+ }
+
+ /**
+ * Use <code>doAnswer()</code> when you want to stub a void method with generic {@link Answer}.
+ * <p>
+ * Stubbing voids requires different approach from {@link Mockito#when(Object)} because the compiler does not like void methods inside brackets...
+ * <p>
+ * Example:
+ *
+ * <pre class="code"><code class="java">
+ * doAnswer(new Answer() {
+ * public Object answer(InvocationOnMock invocation) {
+ * Object[] args = invocation.getArguments();
+ * Mock mock = invocation.getMock();
+ * return null;
+ * }})
+ * .when(mock).someMethod();
+ * </code></pre>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param answer to answer when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static Stubber doAnswer(Answer answer) {
+ return MOCKITO_CORE.doAnswer(answer);
+ }
+
+ /**
+ * Use <code>doNothing()</code> for setting void methods to do nothing. <b>Beware that void methods on mocks do nothing by default!</b>
+ * However, there are rare situations when doNothing() comes handy:
+ * <p>
+ * <ol>
+ * <li>Stubbing consecutive calls on a void method:
+ * <pre class="code"><code class="java">
+ * doNothing().
+ * doThrow(new RuntimeException())
+ * .when(mock).someVoidMethod();
+ *
+ * //does nothing the first time:
+ * mock.someVoidMethod();
+ *
+ * //throws RuntimeException the next time:
+ * mock.someVoidMethod();
+ * </code></pre>
+ * </li>
+ * <li>When you spy real objects and you want the void method to do nothing:
+ * <pre class="code"><code class="java">
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //let's make clear() do nothing
+ * doNothing().when(spy).clear();
+ *
+ * spy.add("one");
+ *
+ * //clear() does nothing, so the list still contains "one"
+ * spy.clear();
+ * </code></pre>
+ * </li>
+ * </ol>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return stubber - to select a method for stubbing
+ */
+ public static Stubber doNothing() {
+ return MOCKITO_CORE.doAnswer(new DoesNothing());
+ }
+
+ /**
+ * Use <code>doReturn()</code> in those rare occasions when you cannot use {@link Mockito#when(Object)}.
+ * <p>
+ * <b>Beware that {@link Mockito#when(Object)} is always recommended for stubbing because it is argument type-safe
+ * and more readable</b> (especially when stubbing consecutive calls).
+ * <p>
+ * Here are those rare occasions when doReturn() comes handy:
+ * <p>
+ *
+ * <ol>
+ * <li>When spying real objects and calling real methods on a spy brings side effects
+ *
+ * <pre class="code"><code class="java">
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ * when(spy.get(0)).thenReturn("foo");
+ *
+ * //You have to use doReturn() for stubbing:
+ * doReturn("foo").when(spy).get(0);
+ * </code></pre>
+ * </li>
+ *
+ * <li>Overriding a previous exception-stubbing:
+ * <pre class="code"><code class="java">
+ * when(mock.foo()).thenThrow(new RuntimeException());
+ *
+ * //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown.
+ * when(mock.foo()).thenReturn("bar");
+ *
+ * //You have to use doReturn() for stubbing:
+ * doReturn("bar").when(mock).foo();
+ * </code></pre>
+ * </li>
+ * </ol>
+ *
+ * Above scenarios shows a tradeoff of Mockito's elegant syntax. Note that the scenarios are very rare, though.
+ * Spying should be sporadic and overriding exception-stubbing is very rare. Not to mention that in general
+ * overridding stubbing is a potential code smell that points out too much stubbing.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param toBeReturned to be returned when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static Stubber doReturn(Object toBeReturned) {
+ return MOCKITO_CORE.doAnswer(new Returns(toBeReturned));
+ }
+
+ /**
+ * Creates {@link org.mockito.InOrder} object that allows verifying mocks in order.
+ *
+ * <pre class="code"><code class="java">
+ * InOrder inOrder = inOrder(firstMock, secondMock);
+ *
+ * inOrder.verify(firstMock).add("was called first");
+ * inOrder.verify(secondMock).add("was called second");
+ * </code></pre>
+ *
+ * Verification in order is flexible - <b>you don't have to verify all interactions</b> one-by-one
+ * but only those that you are interested in testing in order.
+ * <p>
+ * Also, you can create InOrder object passing only mocks that are relevant for in-order verification.
+ * <p>
+ * <code>InOrder</code> verification is 'greedy'. You will hardly every notice it but
+ * if you want to find out more search for 'greedy' on the Mockito
+ * <a href="http://code.google.com/p/mockito/w/list">wiki pages</a>.
+ * <p>
+ * As of Mockito 1.8.4 you can verifyNoMoreInvocations() in order-sensitive way. Read more: {@link InOrder#verifyNoMoreInteractions()}
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mocks to be verified in order
+ *
+ * @return InOrder object to be used to verify in order
+ */
+ public static InOrder inOrder(Object... mocks) {
+ return MOCKITO_CORE.inOrder(mocks);
+ }
+
+ /**
+ * Ignores stubbed methods of given mocks for the sake of verification.
+ * Sometimes useful when coupled with <code>verifyNoMoreInteractions()</code> or verification <code>inOrder()</code>.
+ * Helps avoiding redundant verification of stubbed calls - typically we're not interested in verifying stubs.
+ * <p>
+ * <b>Warning</b>, <code>ignoreStubs()</code> might lead to overuse of <code>verifyNoMoreInteractions(ignoreStubs(...));</code>
+ * Bear in mind that Mockito does not recommend bombarding every test with <code>verifyNoMoreInteractions()</code>
+ * for the reasons outlined in javadoc for {@link Mockito#verifyNoMoreInteractions(Object...)}
+ * Other words: all <b>*stubbed*</b> methods of given mocks are marked <b>*verified*</b> so that they don't get in a way during verifyNoMoreInteractions().
+ * <p>
+ * This method <b>changes the input mocks</b>! This method returns input mocks just for convenience.
+ * <p>
+ * Ignored stubs will also be ignored for verification inOrder, including {@link org.mockito.InOrder#verifyNoMoreInteractions()}.
+ * See the second example.
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * //mocking lists for the sake of the example (if you mock List in real you will burn in hell)
+ * List mock1 = mock(List.class), mock2 = mock(List.class);
+ *
+ * //stubbing mocks:
+ * when(mock1.get(0)).thenReturn(10);
+ * when(mock2.get(0)).thenReturn(20);
+ *
+ * //using mocks by calling stubbed get(0) methods:
+ * System.out.println(mock1.get(0)); //prints 10
+ * System.out.println(mock2.get(0)); //prints 20
+ *
+ * //using mocks by calling clear() methods:
+ * mock1.clear();
+ * mock2.clear();
+ *
+ * //verification:
+ * verify(mock1).clear();
+ * verify(mock2).clear();
+ *
+ * //verifyNoMoreInteractions() fails because get() methods were not accounted for.
+ * try { verifyNoMoreInteractions(mock1, mock2); } catch (NoInteractionsWanted e);
+ *
+ * //However, if we ignore stubbed methods then we can verifyNoMoreInteractions()
+ * verifyNoMoreInteractions(ignoreStubs(mock1, mock2));
+ *
+ * //Remember that ignoreStubs() <b>*changes*</b> the input mocks and returns them for convenience.
+ * </code></pre>
+ * Ignoring stubs can be used with <b>verification in order</b>:
+ * <pre class="code"><code class="java">
+ * List list = mock(List.class);
+ * when(mock.get(0)).thenReturn("foo");
+ *
+ * list.add(0);
+ * System.out.println(list.get(0)); //we don't want to verify this
+ * list.clear();
+ *
+ * InOrder inOrder = inOrder(ignoreStubs(list));
+ * inOrder.verify(list).add(0);
+ * inOrder.verify(list).clear();
+ * inOrder.verifyNoMoreInteractions();
+ * </code></pre>
+ *
+ * @since 1.9.0
+ * @param mocks input mocks that will be changed
+ * @return the same mocks that were passed in as parameters
+ */
+ public static Object[] ignoreStubs(Object... mocks) {
+ return MOCKITO_CORE.ignoreStubs(mocks);
+ }
+
+ /**
+ * Allows verifying exact number of invocations. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, times(2)).someMethod("some arg");
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param wantedNumberOfInvocations wanted number of invocations
+ *
+ * @return verification mode
+ */
+ public static VerificationMode times(int wantedNumberOfInvocations) {
+ return VerificationModeFactory.times(wantedNumberOfInvocations);
+ }
+
+ /**
+ * Alias to <code>times(0)</code>, see {@link Mockito#times(int)}
+ * <p>
+ * Verifies that interaction did not happen. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, never()).someMethod();
+ * </code></pre>
+ *
+ * <p>
+ * If you want to verify there were NO interactions with the mock
+ * check out {@link Mockito#verifyZeroInteractions(Object...)}
+ * or {@link Mockito#verifyNoMoreInteractions(Object...)}
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return verification mode
+ */
+ public static VerificationMode never() {
+ return times(0);
+ }
+
+ /**
+ * Allows at-least-once verification. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, atLeastOnce()).someMethod("some arg");
+ * </code></pre>
+ * Alias to <code>atLeast(1)</code>.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return verification mode
+ */
+ public static VerificationMode atLeastOnce() {
+ return VerificationModeFactory.atLeastOnce();
+ }
+
+ /**
+ * Allows at-least-x verification. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, atLeast(3)).someMethod("some arg");
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param minNumberOfInvocations minimum number of invocations
+ *
+ * @return verification mode
+ */
+ public static VerificationMode atLeast(int minNumberOfInvocations) {
+ return VerificationModeFactory.atLeast(minNumberOfInvocations);
+ }
+
+ /**
+ * Allows at-most-x verification. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, atMost(3)).someMethod("some arg");
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param maxNumberOfInvocations max number of invocations
+ *
+ * @return verification mode
+ */
+ public static VerificationMode atMost(int maxNumberOfInvocations) {
+ return VerificationModeFactory.atMost(maxNumberOfInvocations);
+ }
+
+ /**
+ * Allows non-greedy verification in order. For example
+ * <pre class="code"><code class="java">
+ * inOrder.verify( mock, calls( 2 )).someMethod( "some arg" );
+ * </code></pre>
+ * <ul>
+ * <li>will not fail if the method is called 3 times, unlike times( 2 )</li>
+ * <li>will not mark the third invocation as verified, unlike atLeast( 2 )</li>
+ * </ul>
+ * This verification mode can only be used with in order verification.
+ * @param wantedNumberOfInvocations number of invocations to verify
+ * @return verification mode
+ */
+ public static VerificationMode calls( int wantedNumberOfInvocations ){
+ return VerificationModeFactory.calls( wantedNumberOfInvocations );
+ }
+
+ /**
+ * Allows checking if given method was the only one invoked. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, only()).someMethod();
+ * //above is a shorthand for following 2 lines of code:
+ * verify(mock).someMethod();
+ * verifyNoMoreInvocations(mock);
+ * </code></pre>
+ *
+ * <p>
+ * See also {@link Mockito#verifyNoMoreInteractions(Object...)}
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return verification mode
+ */
+ public static VerificationMode only() {
+ return VerificationModeFactory.only();
+ }
+
+ /**
+ * Allows verifying with timeout. It causes a verify to wait for a specified period of time for a desired
+ * interaction rather than fails immediately if had not already happened. May be useful for testing in concurrent
+ * conditions.
+ * <p>
+ * It feels this feature should be used rarely - figure out a better way of testing your multi-threaded system
+ * <p>
+ * Not yet implemented to work with InOrder verification.
+ * <pre class="code"><code class="java">
+ * //passes when someMethod() is called within given time span
+ * verify(mock, timeout(100)).someMethod();
+ * //above is an alias to:
+ * verify(mock, timeout(100).times(1)).someMethod();
+ *
+ * //passes when someMethod() is called <b>*exactly*</b> 2 times within given time span
+ * verify(mock, timeout(100).times(2)).someMethod();
+ *
+ * //passes when someMethod() is called <b>*at least*</b> 2 times within given time span
+ * verify(mock, timeout(100).atLeast(2)).someMethod();
+ *
+ * //verifies someMethod() within given time span using given verification mode
+ * //useful only if you have your own custom verification modes.
+ * verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param millis - time span in millisecond
+ *
+ * @return verification mode
+ */
+ public static VerificationWithTimeout timeout(int millis) {
+ return new Timeout(millis, VerificationModeFactory.times(1));
+ }
+
+ /**
+ * First of all, in case of any trouble, I encourage you to read the Mockito FAQ: <a href="http://code.google.com/p/mockito/wiki/FAQ">http://code.google.com/p/mockito/wiki/FAQ</a>
+ * <p>
+ * In case of questions you may also post to mockito mailing list: <a href="http://groups.google.com/group/mockito">http://groups.google.com/group/mockito</a>
+ * <p>
+ * <code>validateMockitoUsage()</code> <b>explicitly validates</b> the framework state to detect invalid use of Mockito.
+ * However, this feature is optional <b>because Mockito validates the usage all the time...</b> but there is a gotcha so read on.
+ * <p>
+ * Examples of incorrect use:
+ * <pre class="code"><code class="java">
+ * //Oups, someone forgot thenReturn() part:
+ * when(mock.get());
+ *
+ * //Oups, someone put the verified method call inside verify() where it should be outside:
+ * verify(mock.execute());
+ *
+ * //Oups, someone has used EasyMock for too long and forgot to specify the method to verify:
+ * verify(mock);
+ * </code></pre>
+ *
+ * Mockito throws exceptions if you misuse it so that you know if your tests are written correctly.
+ * The gotcha is that Mockito does the validation <b>next time</b> you use the framework (e.g. next time you verify, stub, call mock etc.).
+ * But even though the exception might be thrown in the next test,
+ * the exception <b>message contains a navigable stack trace element</b> with location of the defect.
+ * Hence you can click and find the place where Mockito was misused.
+ * <p>
+ * Sometimes though, you might want to validate the framework usage explicitly.
+ * For example, one of the users wanted to put <code>validateMockitoUsage()</code> in his <code>@After</code> method
+ * so that he knows immediately when he misused Mockito.
+ * Without it, he would have known about it not sooner than <b>next time</b> he used the framework.
+ * One more benefit of having <code>validateMockitoUsage()</code> in <code>@After</code> is that jUnit runner will always fail in the test method with defect
+ * whereas ordinary 'next-time' validation might fail the <b>next</b> test method.
+ * But even though JUnit might report next test as red, don't worry about it
+ * and just click at navigable stack trace element in the exception message to instantly locate the place where you misused mockito.
+ * <p>
+ * <b>Built-in runner: {@link MockitoJUnitRunner}</b> does validateMockitoUsage() after each test method.
+ * <p>
+ * Bear in mind that <b>usually you don't have to <code>validateMockitoUsage()</code></b>
+ * and framework validation triggered on next-time basis should be just enough,
+ * mainly because of enhanced exception message with clickable location of defect.
+ * However, I would recommend validateMockitoUsage() if you already have sufficient test infrastructure
+ * (like your own runner or base class for all tests) because adding a special action to <code>@After</code> has zero cost.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ */
+ public static void validateMockitoUsage() {
+ MOCKITO_CORE.validateMockitoUsage();
+ }
+
+ /**
+ * Allows mock creation with additional mock settings.
+ * <p>
+ * Don't use it too often.
+ * Consider writing simple tests that use simple mocks.
+ * Repeat after me: simple tests push simple, KISSy, readable & maintainable code.
+ * If you cannot write a test in a simple way - refactor the code under test.
+ * <p>
+ * Examples of mock settings:
+ * <pre class="code"><code class="java">
+ * //Creates mock with different default answer & name
+ * Foo mock = mock(Foo.class, withSettings()
+ * .defaultAnswer(RETURNS_SMART_NULLS)
+ * .name("cool mockie"));
+ *
+ * //Creates mock with different default answer, descriptive name and extra interfaces
+ * Foo mock = mock(Foo.class, withSettings()
+ * .defaultAnswer(RETURNS_SMART_NULLS)
+ * .name("cool mockie")
+ * .extraInterfaces(Bar.class));
+ * </code></pre>
+ * {@link MockSettings} has been introduced for two reasons.
+ * Firstly, to make it easy to add another mock settings when the demand comes.
+ * Secondly, to enable combining different mock settings without introducing zillions of overloaded mock() methods.
+ * <p>
+ * See javadoc for {@link MockSettings} to learn about possible mock settings.
+ * <p>
+ *
+ * @return mock settings instance with defaults.
+ */
+ public static MockSettings withSettings() {
+ return new MockSettingsImpl().defaultAnswer(RETURNS_DEFAULTS);
+ }
+
+ /**
+ * Helps debugging failing tests. Experimental - use at your own risk. We're not sure if this method will stay in public api.
+ */
+ @Deprecated
+ static MockitoDebugger debug() {
+ return new MockitoDebuggerImpl();
+ }
+}
diff --git a/src/org/mockito/MockitoAnnotations.java b/src/org/mockito/MockitoAnnotations.java
new file mode 100644
index 0000000..d02afa4
--- /dev/null
+++ b/src/org/mockito/MockitoAnnotations.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito;
+
+import org.mockito.configuration.AnnotationEngine;
+import org.mockito.configuration.DefaultMockitoConfiguration;
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.configuration.GlobalConfiguration;
+import org.mockito.internal.util.reflection.FieldSetter;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Field;
+
+import static java.lang.annotation.ElementType.FIELD;
+
+/**
+ * MockitoAnnotations.initMocks(this); initializes fields annotated with Mockito annotations.
+ * <p>
+ * <ul>
+ * <li>Allows shorthand creation of objects required for testing.</li>
+ * <li>Minimizes repetitive mock creation code.</li>
+ * <li>Makes the test class more readable.</li>
+ * <li>Makes the verification error easier to read because <b>field name</b> is used to identify the mock.</li>
+ * </ul>
+ *
+ * <pre class="code"><code class="java">
+ * public class ArticleManagerTest extends SampleBaseTestCase {
+ *
+ * @Mock private ArticleCalculator calculator;
+ * @Mock private ArticleDatabase database;
+ * @Mock private UserProvider userProvider;
+ *
+ * private ArticleManager manager;
+ *
+ * @Before public void setup() {
+ * manager = new ArticleManager(userProvider, database, calculator);
+ * }
+ * }
+ *
+ * public class SampleBaseTestCase {
+ *
+ * @Before public void initMocks() {
+ * MockitoAnnotations.initMocks(this);
+ * }
+ * }
+ * </code></pre>
+ * <p>
+ * Read also about other annotations @{@link Spy}, @{@link Captor}, @{@link InjectMocks}
+ * <p>
+ * <b><code>MockitoAnnotations.initMocks(this)</code></b> method has to called to initialize annotated fields.
+ * <p>
+ * In above example, <code>initMocks()</code> is called in @Before (JUnit4) method of test's base class.
+ * For JUnit3 <code>initMocks()</code> can go to <code>setup()</code> method of a base class.
+ * You can also put initMocks() in your JUnit runner (@RunWith) or use built-in runner: {@link MockitoJUnitRunner}
+ */
+public class MockitoAnnotations {
+
+ /**
+ * Use top-level {@link org.mockito.Mock} annotation instead
+ * <p>
+ * When @Mock annotation was implemented as an inner class then users experienced problems with autocomplete features in IDEs.
+ * Hence @Mock was made a top-level class.
+ * <p>
+ * How to fix deprecation warnings?
+ * Typically, you can just <b>search:</b> import org.mockito.MockitoAnnotations.Mock; <b>and replace with:</b> import org.mockito.Mock;
+ * <p>
+ * If you're an existing user then sorry for making your code littered with deprecation warnings.
+ * This change was required to make Mockito better.
+ */
+ @Target( { FIELD })
+ @Retention(RetentionPolicy.RUNTIME)
+ @Deprecated
+ public @interface Mock {}
+
+ /**
+ * Initializes objects annotated with Mockito annotations for given testClass:
+ * @{@link org.mockito.Mock}, @{@link Spy}, @{@link Captor}, @{@link InjectMocks}
+ * <p>
+ * See examples in javadoc for {@link MockitoAnnotations} class.
+ */
+ public static void initMocks(Object testClass) {
+ if (testClass == null) {
+ throw new MockitoException("testClass cannot be null. For info how to use @Mock annotations see examples in javadoc for MockitoAnnotations class");
+ }
+
+ AnnotationEngine annotationEngine = new GlobalConfiguration().getAnnotationEngine();
+ Class<?> clazz = testClass.getClass();
+
+ //below can be removed later, when we get read rid of deprecated stuff
+ if (annotationEngine.getClass() != new DefaultMockitoConfiguration().getAnnotationEngine().getClass()) {
+ //this means user has his own annotation engine and we have to respect that.
+ //we will do annotation processing the old way so that we are backwards compatible
+ while (clazz != Object.class) {
+ scanDeprecatedWay(annotationEngine, testClass, clazz);
+ clazz = clazz.getSuperclass();
+ }
+ }
+
+ //anyway act 'the new' way
+ annotationEngine.process(testClass.getClass(), testClass);
+ }
+
+ static void scanDeprecatedWay(AnnotationEngine annotationEngine, Object testClass, Class<?> clazz) {
+ Field[] fields = clazz.getDeclaredFields();
+
+ for (Field field : fields) {
+ processAnnotationDeprecatedWay(annotationEngine, testClass, field);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ static void processAnnotationDeprecatedWay(AnnotationEngine annotationEngine, Object testClass, Field field) {
+ boolean alreadyAssigned = false;
+ for(Annotation annotation : field.getAnnotations()) {
+ Object mock = annotationEngine.createMockFor(annotation, field);
+ if (mock != null) {
+ throwIfAlreadyAssigned(field, alreadyAssigned);
+ alreadyAssigned = true;
+ try {
+ new FieldSetter(testClass, field).set(mock);
+ } catch (Exception e) {
+ throw new MockitoException("Problems setting field " + field.getName() + " annotated with "
+ + annotation, e);
+ }
+ }
+ }
+ }
+
+ static void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) {
+ if (alreadyAssigned) {
+ new Reporter().moreThanOneAnnotationNotAllowed(field.getName());
+ }
+ }
+}
diff --git a/src/org/mockito/MockitoDebugger.java b/src/org/mockito/MockitoDebugger.java
new file mode 100644
index 0000000..496f3d7
--- /dev/null
+++ b/src/org/mockito/MockitoDebugger.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+public interface MockitoDebugger {
+
+ //Prints all interactions with mock. Also prints stubbing information.
+ //You can put it in your 'tearDown' method
+ String printInvocations(Object ... mocks);
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/ReturnValues.java b/src/org/mockito/ReturnValues.java
new file mode 100644
index 0000000..f940212
--- /dev/null
+++ b/src/org/mockito/ReturnValues.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * @deprecated
+ * <b>Instead, please use {@link Answer} interface</b>
+ * <p>
+ * In rare cases your code might not compile with recent deprecation & changes.
+ * Very sorry for inconvenience but it had to be done in order to keep framework consistent.
+ * <p>
+ * Why it is deprecated? ReturnValues is being replaced by Answer
+ * for better consistency & interoperability of the framework.
+ * Answer interface has been in Mockito for a while and it has the same responsibility as ReturnValues.
+ * There's no point in mainting exactly the same interfaces.
+ * <p>
+ * Configures return values for an unstubbed invocation
+ * <p>
+ * Can be used in {@link Mockito#mock(Class, ReturnValues)}
+ */
+@Deprecated
+public interface ReturnValues {
+
+ /**
+ * return value for an unstubbed invocation
+ *
+ * @param invocation placeholder for mock and a method
+ * @return the return value
+ */
+ Object valueFor(InvocationOnMock invocation) throws Throwable;
+}
\ No newline at end of file
diff --git a/src/org/mockito/Spy.java b/src/org/mockito/Spy.java
new file mode 100644
index 0000000..5f0d564
--- /dev/null
+++ b/src/org/mockito/Spy.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito;
+
+import java.lang.annotation.*;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Allows shorthand wrapping of field instances in an spy object.
+ *
+ * <p>
+ * Example:
+ *
+ * <pre class="code"><code class="java">
+ * public class Test{
+ * //Instance for spying is created by calling constructor explicitly:
+ * @Spy Foo spyOnFoo = new Foo("argument");
+ * //Instance for spying is created by mockito via reflection (only default constructors supported):
+ * @Spy Bar spyOnBar;
+ * @Before
+ * public void init(){
+ * MockitoAnnotations.initMocks(this);
+ * }
+ * ...
+ * }
+ * </code></pre>
+ * <p>
+ * Same as doing:
+ *
+ * <pre class="code"><code class="java">
+ * Foo spyOnFoo = Mockito.spy(new Foo("argument"));
+ * Bar spyOnFoo = Mockito.spy(new Bar());
+ * </code></pre>
+ *
+ * <p>
+ * <strong>The field annotated with @Spy can be initialized by Mockito if a zero argument constructor
+ * can be found in the type (even private). <u>But Mockito cannot instantiate inner classes, local classes,
+ * abstract classes and interfaces.</u></strong>
+ *
+ * <strong>The field annotated with @Spy can be initialized explicitly at declaration point.
+ * Alternatively, if you don't provide the instance Mockito will try to find zero argument constructor (even private)
+ * and create an instance for you.
+ * <u>But Mockito cannot instantiate inner classes, local classes, abstract classes and interfaces.</u></strong>
+ *
+ * For example this class can be instantiated by Mockito :
+ * <pre class="code"><code class="java">public class Bar {
+ * private Bar() {}
+ * public Bar(String publicConstructorWithOneArg) {}
+ * }</code></pre>
+ * </p>
+ *
+ * <h4>Important gotcha on spying real objects!</h4>
+ * <ol>
+ * <li>Sometimes it's impossible or impractical to use {@link Mockito#when(Object)} for stubbing spies.
+ * Therefore for spies it is recommended to always use <code>doReturn</code>|<code>Answer</code>|<code>Throw()</code>|<code>CallRealMethod</code>
+ * family of methods for stubbing. Example:
+ *
+ * <pre class="code"><code class="java">
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ * when(spy.get(0)).thenReturn("foo");
+ *
+ * //You have to use doReturn() for stubbing
+ * doReturn("foo").when(spy).get(0);
+ * </code></pre>
+ * </li>
+ *
+ * <li>Mockito <b>*does not*</b> delegate calls to the passed real instance, instead it actually creates a copy of it.
+ * So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction
+ * and their effect on real instance state.
+ * The corollary is that when an <b>*unstubbed*</b> method is called <b>*on the spy*</b> but <b>*not on the real instance*</b>,
+ * you won't see any effects on the real instance.</li>
+ *
+ * <li>Watch out for final methods.
+ * Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble.
+ * Also you won't be able to verify those method as well.
+ * </li>
+ * </ol>
+ *
+ * <p>
+ * <strong>One last warning :</strong> if you call <code>MockitoAnnotations.initMocks(this)</code> in a
+ * super class <strong>constructor</strong> then this will not work. It is because fields
+ * in subclass are only instantiated after super class constructor has returned.
+ * It's better to use @Before.
+ * <strong>Instead</strong> you can also put initMocks() in your JUnit runner (@RunWith) or use the built-in
+ * {@link org.mockito.runners.MockitoJUnitRunner}.
+ * </p>
+ *
+ * @see Mockito#spy(Object)
+ * @see Mock
+ * @see InjectMocks
+ * @see MockitoAnnotations#initMocks(Object)
+ * @see org.mockito.runners.MockitoJUnitRunner
+ * @since 1.8.3
+ */
+@Retention(RUNTIME)
+@Target(FIELD)
+@Documented
+public @interface Spy { }
diff --git a/src/org/mockito/configuration/AnnotationEngine.java b/src/org/mockito/configuration/AnnotationEngine.java
new file mode 100644
index 0000000..ecd4461
--- /dev/null
+++ b/src/org/mockito/configuration/AnnotationEngine.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.configuration;
+
+import org.mockito.MockitoAnnotations;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+/**
+ * Configures mock creation logic behind @Mock, @Captor and @Spy annotations
+ * <p>
+ * If you are interested then see implementations or source code of {@link MockitoAnnotations#initMocks(Object)}
+ */
+public interface AnnotationEngine {
+
+ /**
+ * @deprecated
+ * Please use {@link AnnotationEngine#process(Class, Object)} method instead that is more robust
+ * <p>
+ * Creates mock, ArgumentCaptor or wraps field instance in spy object.
+ * Only if of correct annotation type.
+ *
+ * @param annotation Annotation
+ * @param field Field details
+ */
+ @Deprecated
+ Object createMockFor(Annotation annotation, Field field);
+
+ /**
+ * Allows extending the interface to perform action on specific fields on the test class.
+ * <p>
+ * See the implementation of this method to figure out what is it for.
+ *
+ * @param clazz Class where to extract field information, check implementation for details
+ * @param testInstance Test instance
+ */
+ void process(Class<?> clazz, Object testInstance);
+}
\ No newline at end of file
diff --git a/src/org/mockito/configuration/DefaultMockitoConfiguration.java b/src/org/mockito/configuration/DefaultMockitoConfiguration.java
new file mode 100644
index 0000000..8fdfc76
--- /dev/null
+++ b/src/org/mockito/configuration/DefaultMockitoConfiguration.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.configuration;
+
+import org.mockito.ReturnValues;
+import org.mockito.internal.configuration.InjectingAnnotationEngine;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.stubbing.Answer;
+
+/**
+ * DefaultConfiguration of Mockito framework
+ * <p>
+ * Currently it doesn't have many configuration options but it will probably change if future.
+ * <p>
+ * See javadocs for {@link IMockitoConfiguration} on info how to configure Mockito
+ */
+@SuppressWarnings("deprecation")//supressed until ReturnValues are removed
+public class DefaultMockitoConfiguration implements IMockitoConfiguration {
+
+ /* (non-Javadoc)
+ * @see org.mockito.IMockitoConfiguration#getReturnValues()
+ */
+ @Deprecated
+ public ReturnValues getReturnValues() {
+ throw new RuntimeException("\n" + "This method should not be used by the framework because it was deprecated"
+ + "\n" + "Please report the failure to the Mockito mailing list");
+ }
+
+ public Answer<Object> getDefaultAnswer() {
+ return new ReturnsEmptyValues();
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.IMockitoConfiguration#getAnnotationEngine()
+ */
+ public AnnotationEngine getAnnotationEngine() {
+ return new InjectingAnnotationEngine();
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.configuration.IMockitoConfiguration#cleansStackTrace()
+ */
+ public boolean cleansStackTrace() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.configuration.IMockitoConfiguration#enableClassCache()
+ */
+ public boolean enableClassCache() {
+ return true;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/configuration/IMockitoConfiguration.java b/src/org/mockito/configuration/IMockitoConfiguration.java
new file mode 100644
index 0000000..05ecb87
--- /dev/null
+++ b/src/org/mockito/configuration/IMockitoConfiguration.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.configuration;
+
+import org.mockito.ReturnValues;
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Use it to configure Mockito. For now there are not many configuration options but it may change in future.
+ * <p>
+ * In most cases you don't really need to configure Mockito. For example in case of working with legacy code,
+ * when you might want to have different 'mocking style' this interface might be helpful.
+ * A reason of configuring Mockito might be if you disagree with the {@link ReturnsEmptyValues} unstubbed mocks return.
+ * <p>
+ * To configure Mockito create exactly <b>org.mockito.configuration.MockitoConfiguration</b> class that implements this interface.
+ * <p>
+ * Configuring Mockito is completely <b>optional</b> - nothing happens if there isn't any <b>org.mockito.configuration.MockitoConfiguration</b> on the classpath.
+ * <p>
+ * <b>org.mockito.configuration.MockitoConfiguration</b> must implement IMockitoConfiguration or extend {@link DefaultMockitoConfiguration}
+ * <p>
+ * Mockito will store single instance of org.mockito.configuration.MockitoConfiguration per thread (using ThreadLocal).
+ * For sanity of your tests, don't make the implementation stateful.
+ * <p>
+ * If you have comments on Mockito configuration feature don't hesitate to write to mockito@googlegroups.com
+ */
+@SuppressWarnings("deprecation")//supressed until ReturnValues are removed
+public interface IMockitoConfiguration {
+
+ /**
+ * @deprecated
+ * <b>Please use {@link IMockitoConfiguration#getDefaultAnswer()}</b>
+ * <p>
+ * Steps:
+ * <p>
+ * 1. Leave the implementation of getReturnValues() method empty - it's not going to be used anyway.
+ * <p>
+ * 2. Implement getDefaultAnswer() instead.
+ * <p>
+ * In rare cases your code might not compile with recent deprecation & changes.
+ * Very sorry for inconvenience but it had to be done in order to keep framework consistent.
+ * <p>
+ * See javadoc {@link ReturnValues} for info why this method was deprecated
+ * <p>
+ * Allows configuring the default return values of unstubbed invocations
+ * <p>
+ * See javadoc for {@link IMockitoConfiguration}
+ */
+ @Deprecated
+ ReturnValues getReturnValues();
+
+ /**
+ * Allows configuring the default answers of unstubbed invocations
+ * <p>
+ * See javadoc for {@link IMockitoConfiguration}
+ */
+ Answer<Object> getDefaultAnswer();
+
+ /**
+ * Configures annotations for mocks
+ * <p>
+ * See javadoc for {@link IMockitoConfiguration}
+ */
+ AnnotationEngine getAnnotationEngine();
+
+ /**
+ * This should be turned on unless you're a Mockito developer and you wish
+ * to have verbose (read: messy) stack traces that only few understand (eg:
+ * Mockito developers)
+ * <p>
+ * See javadoc for {@link IMockitoConfiguration}
+ *
+ * @return if Mockito should clean stack traces
+ */
+ boolean cleansStackTrace();
+
+ /**
+ * Allow objenesis to cache classes. If you're in an environment where classes
+ * are dynamically reloaded, you can disable this to avoid classcast exceptions.
+ */
+ boolean enableClassCache();
+}
\ No newline at end of file
diff --git a/src/org/mockito/configuration/package.html b/src/org/mockito/configuration/package.html
new file mode 100644
index 0000000..b4bec23
--- /dev/null
+++ b/src/org/mockito/configuration/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Mockito configuration utilities
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/Discrepancy.java b/src/org/mockito/exceptions/Discrepancy.java
new file mode 100644
index 0000000..570c469
--- /dev/null
+++ b/src/org/mockito/exceptions/Discrepancy.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.exceptions;
+
+@Deprecated
+/**
+ * @Deprecated. This class has been moved to internal packages because it was never meant to be public.
+ * If you need it for extending Mockito please let us know. You can still use {@link org.mockito.internal.reporting.Discrepancy}.
+ * However, the package clearly states that the class in a part of a public API so it can change.
+ */
+public class Discrepancy extends org.mockito.internal.reporting.Discrepancy {
+ public Discrepancy(int wantedCount, int actualCount) {
+ super(wantedCount, actualCount);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/Pluralizer.java b/src/org/mockito/exceptions/Pluralizer.java
new file mode 100644
index 0000000..8fdad39
--- /dev/null
+++ b/src/org/mockito/exceptions/Pluralizer.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.exceptions;
+
+@Deprecated
+/**
+ * @Deprecated. This class has been moved to internal packages because it was never meant to be public.
+ * If you need it for extending Mockito please let us know. You can still use {@link org.mockito.internal.reporting.Pluralizer}.
+ * However, the package clearly states that the class in a part of a public API so it can change.
+ */
+public class Pluralizer extends org.mockito.internal.reporting.Pluralizer {}
diff --git a/src/org/mockito/exceptions/PrintableInvocation.java b/src/org/mockito/exceptions/PrintableInvocation.java
new file mode 100644
index 0000000..52e288d
--- /dev/null
+++ b/src/org/mockito/exceptions/PrintableInvocation.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions;
+
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Location;
+
+@Deprecated
+/**
+ * @Deprecated. We needed to move this class to a better place to keep consistency of the API.
+ * Please use {@link DescribedInvocation} instead.
+ */
+public interface PrintableInvocation {
+
+ String toString();
+
+ Location getLocation();
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/Reporter.java b/src/org/mockito/exceptions/Reporter.java
new file mode 100644
index 0000000..aaa2aff
--- /dev/null
+++ b/src/org/mockito/exceptions/Reporter.java
@@ -0,0 +1,766 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.*;
+import org.mockito.exceptions.verification.*;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.internal.exceptions.VerificationAwareInvocation;
+import org.mockito.internal.exceptions.util.ScenarioPrinter;
+import org.mockito.internal.junit.JUnitTool;
+import org.mockito.internal.matchers.LocalizedMatcher;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.StringJoiner;
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.invocation.Location;
+import org.mockito.listeners.InvocationListener;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static org.mockito.internal.reporting.Pluralizer.pluralize;
+import static org.mockito.internal.util.StringJoiner.join;
+
+/**
+ * Reports verification and misusing errors.
+ * <p>
+ * One of the key points of mocking library is proper verification/exception
+ * messages. All messages in one place makes it easier to tune and amend them.
+ * <p>
+ * Reporter can be injected and therefore is easily testable.
+ * <p>
+ * Generally, exception messages are full of line breaks to make them easy to
+ * read (xunit plugins take only fraction of screen on modern IDEs).
+ */
+public class Reporter {
+
+ public void checkedExceptionInvalid(Throwable t) {
+ throw new MockitoException(join(
+ "Checked exception is invalid for this method!",
+ "Invalid: " + t
+ ));
+ }
+
+ public void cannotStubWithNullThrowable() {
+ throw new MockitoException(join(
+ "Cannot stub with null throwable!"
+ ));
+
+ }
+
+ public void unfinishedStubbing(Location location) {
+ throw new UnfinishedStubbingException(join(
+ "Unfinished stubbing detected here:",
+ location,
+ "",
+ "E.g. thenReturn() may be missing.",
+ "Examples of correct stubbing:",
+ " when(mock.isOk()).thenReturn(true);",
+ " when(mock.isOk()).thenThrow(exception);",
+ " doThrow(exception).when(mock).someVoidMethod();",
+ "Hints:",
+ " 1. missing thenReturn()",
+ " 2. you are trying to stub a final method, you naughty developer!",
+ ""
+ ));
+ }
+
+ public void incorrectUseOfApi() {
+ throw new MockitoException(join(
+ "Incorrect use of API detected here:",
+ new LocationImpl(),
+ "",
+ "You probably stored a reference to OngoingStubbing returned by when() and called stubbing methods like thenReturn() on this reference more than once.",
+ "Examples of correct usage:",
+ " when(mock.isOk()).thenReturn(true).thenReturn(false).thenThrow(exception);",
+ " when(mock.isOk()).thenReturn(true, false).thenThrow(exception);",
+ ""
+ ));
+ }
+
+ public void missingMethodInvocation() {
+ throw new MissingMethodInvocationException(join(
+ "when() requires an argument which has to be 'a method call on a mock'.",
+ "For example:",
+ " when(mock.getArticles()).thenReturn(articles);",
+ "",
+ "Also, this error might show up because:",
+ "1. you stub either of: final/private/equals()/hashCode() methods.",
+ " Those methods *cannot* be stubbed/verified.",
+ "2. inside when() you don't call method on mock but on some other object.",
+ "3. the parent of the mocked class is not public.",
+ " It is a limitation of the mock engine.",
+ ""
+ ));
+ }
+
+ public void unfinishedVerificationException(Location location) {
+ UnfinishedVerificationException exception = new UnfinishedVerificationException(join(
+ "Missing method call for verify(mock) here:",
+ location,
+ "",
+ "Example of correct verification:",
+ " verify(mock).doSomething()",
+ "",
+ "Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.",
+ "Those methods *cannot* be stubbed/verified.",
+ ""
+ ));
+
+ throw exception;
+ }
+
+ public void notAMockPassedToVerify(Class type) {
+ throw new NotAMockException(join(
+ "Argument passed to verify() is of type " + type.getSimpleName() + " and is not a mock!",
+ "Make sure you place the parenthesis correctly!",
+ "See the examples of correct verifications:",
+ " verify(mock).someMethod();",
+ " verify(mock, times(10)).someMethod();",
+ " verify(mock, atLeastOnce()).someMethod();"
+ ));
+ }
+
+ public void nullPassedToVerify() {
+ throw new NullInsteadOfMockException(join(
+ "Argument passed to verify() should be a mock but is null!",
+ "Examples of correct verifications:",
+ " verify(mock).someMethod();",
+ " verify(mock, times(10)).someMethod();",
+ " verify(mock, atLeastOnce()).someMethod();",
+ "Also, if you use @Mock annotation don't miss initMocks()"
+ ));
+ }
+
+ public void notAMockPassedToWhenMethod() {
+ throw new NotAMockException(join(
+ "Argument passed to when() is not a mock!",
+ "Example of correct stubbing:",
+ " doThrow(new RuntimeException()).when(mock).someMethod();"
+ ));
+ }
+
+ public void nullPassedToWhenMethod() {
+ throw new NullInsteadOfMockException(join(
+ "Argument passed to when() is null!",
+ "Example of correct stubbing:",
+ " doThrow(new RuntimeException()).when(mock).someMethod();",
+ "Also, if you use @Mock annotation don't miss initMocks()"
+ ));
+ }
+
+ public void mocksHaveToBePassedToVerifyNoMoreInteractions() {
+ throw new MockitoException(join(
+ "Method requires argument(s)!",
+ "Pass mocks that should be verified, e.g:",
+ " verifyNoMoreInteractions(mockOne, mockTwo);",
+ " verifyZeroInteractions(mockOne, mockTwo);",
+ ""
+ ));
+ }
+
+ public void notAMockPassedToVerifyNoMoreInteractions() {
+ throw new NotAMockException(join(
+ "Argument(s) passed is not a mock!",
+ "Examples of correct verifications:",
+ " verifyNoMoreInteractions(mockOne, mockTwo);",
+ " verifyZeroInteractions(mockOne, mockTwo);",
+ ""
+ ));
+ }
+
+ public void nullPassedToVerifyNoMoreInteractions() {
+ throw new NullInsteadOfMockException(join(
+ "Argument(s) passed is null!",
+ "Examples of correct verifications:",
+ " verifyNoMoreInteractions(mockOne, mockTwo);",
+ " verifyZeroInteractions(mockOne, mockTwo);"
+ ));
+ }
+
+ public void notAMockPassedWhenCreatingInOrder() {
+ throw new NotAMockException(join(
+ "Argument(s) passed is not a mock!",
+ "Pass mocks that require verification in order.",
+ "For example:",
+ " InOrder inOrder = inOrder(mockOne, mockTwo);"
+ ));
+ }
+
+ public void nullPassedWhenCreatingInOrder() {
+ throw new NullInsteadOfMockException(join(
+ "Argument(s) passed is null!",
+ "Pass mocks that require verification in order.",
+ "For example:",
+ " InOrder inOrder = inOrder(mockOne, mockTwo);"
+ ));
+ }
+
+ public void mocksHaveToBePassedWhenCreatingInOrder() {
+ throw new MockitoException(join(
+ "Method requires argument(s)!",
+ "Pass mocks that require verification in order.",
+ "For example:",
+ " InOrder inOrder = inOrder(mockOne, mockTwo);"
+ ));
+ }
+
+ public void inOrderRequiresFamiliarMock() {
+ throw new MockitoException(join(
+ "InOrder can only verify mocks that were passed in during creation of InOrder.",
+ "For example:",
+ " InOrder inOrder = inOrder(mockOne);",
+ " inOrder.verify(mockOne).doStuff();"
+ ));
+ }
+
+ public void invalidUseOfMatchers(int expectedMatchersCount, List<LocalizedMatcher> recordedMatchers) {
+ throw new InvalidUseOfMatchersException(join(
+ "Invalid use of argument matchers!",
+ expectedMatchersCount + " matchers expected, " + recordedMatchers.size()+ " recorded:" +
+ locationsOf(recordedMatchers),
+ "",
+ "This exception may occur if matchers are combined with raw values:",
+ " //incorrect:",
+ " someMethod(anyObject(), \"raw String\");",
+ "When using matchers, all arguments have to be provided by matchers.",
+ "For example:",
+ " //correct:",
+ " someMethod(anyObject(), eq(\"String by matcher\"));",
+ "",
+ "For more info see javadoc for Matchers class.",
+ ""
+ ));
+ }
+
+ public void incorrectUseOfAdditionalMatchers(String additionalMatcherName, int expectedSubMatchersCount, Collection<LocalizedMatcher> matcherStack) {
+ throw new InvalidUseOfMatchersException(join(
+ "Invalid use of argument matchers inside additional matcher " + additionalMatcherName + " !",
+ new LocationImpl(),
+ "",
+ expectedSubMatchersCount + " sub matchers expected, " + matcherStack.size() + " recorded:",
+ locationsOf(matcherStack),
+ "",
+ "This exception may occur if matchers are combined with raw values:",
+ " //incorrect:",
+ " someMethod(AdditionalMatchers.and(isNotNull(), \"raw String\");",
+ "When using matchers, all arguments have to be provided by matchers.",
+ "For example:",
+ " //correct:",
+ " someMethod(AdditionalMatchers.and(isNotNull(), eq(\"raw String\"));",
+ "",
+ "For more info see javadoc for Matchers and AdditionalMatchers classes.",
+ ""
+ ));
+ }
+
+ public void stubPassedToVerify() {
+ throw new CannotVerifyStubOnlyMock(join(
+ "Argument passed to verify() is a stubOnly() mock, not a full blown mock!",
+ "If you intend to verify invocations on a mock, don't use stubOnly() in its MockSettings."
+ ));
+ }
+
+ public void reportNoSubMatchersFound(String additionalMatcherName) {
+ throw new InvalidUseOfMatchersException(join(
+ "No matchers found for additional matcher " + additionalMatcherName,
+ new LocationImpl(),
+ ""
+ ));
+ }
+
+
+ private Object locationsOf(Collection<LocalizedMatcher> matchers) {
+ List<String> description = new ArrayList<String>();
+ for (LocalizedMatcher matcher : matchers)
+ description.add(matcher.getLocation().toString());
+ return join(description.toArray());
+ }
+
+ public void argumentsAreDifferent(String wanted, String actual, Location actualLocation) {
+ String message = join("Argument(s) are different! Wanted:",
+ wanted,
+ new LocationImpl(),
+ "Actual invocation has different arguments:",
+ actual,
+ actualLocation,
+ ""
+ );
+
+ if (JUnitTool.hasJUnit()) {
+ throw JUnitTool.createArgumentsAreDifferentException(message, wanted, actual);
+ } else {
+ throw new ArgumentsAreDifferent(message);
+ }
+ }
+
+ public void wantedButNotInvoked(DescribedInvocation wanted) {
+ throw new WantedButNotInvoked(createWantedButNotInvokedMessage(wanted));
+ }
+
+ public void wantedButNotInvoked(DescribedInvocation wanted, List<? extends DescribedInvocation> invocations) {
+ String allInvocations;
+ if (invocations.isEmpty()) {
+ allInvocations = "Actually, there were zero interactions with this mock.\n";
+ } else {
+ StringBuilder sb = new StringBuilder("\nHowever, there were other interactions with this mock:\n");
+ for (DescribedInvocation i : invocations) {
+ sb.append(i.toString())
+ .append("\n")
+ .append(i.getLocation())
+ .append("\n\n");
+ }
+ allInvocations = sb.toString();
+ }
+
+ String message = createWantedButNotInvokedMessage(wanted);
+ throw new WantedButNotInvoked(message + allInvocations);
+ }
+
+ private String createWantedButNotInvokedMessage(DescribedInvocation wanted) {
+ return join(
+ "Wanted but not invoked:",
+ wanted.toString(),
+ new LocationImpl(),
+ ""
+ );
+ }
+
+ public void wantedButNotInvokedInOrder(DescribedInvocation wanted, DescribedInvocation previous) {
+ throw new VerificationInOrderFailure(join(
+ "Verification in order failure",
+ "Wanted but not invoked:",
+ wanted.toString(),
+ new LocationImpl(),
+ "Wanted anywhere AFTER following interaction:",
+ previous.toString(),
+ previous.getLocation(),
+ ""
+ ));
+ }
+
+ public void tooManyActualInvocations(int wantedCount, int actualCount, DescribedInvocation wanted, Location firstUndesired) {
+ String message = createTooManyInvocationsMessage(wantedCount, actualCount, wanted, firstUndesired);
+ throw new TooManyActualInvocations(message);
+ }
+
+ private String createTooManyInvocationsMessage(int wantedCount, int actualCount, DescribedInvocation wanted,
+ Location firstUndesired) {
+ return join(
+ wanted.toString(),
+ "Wanted " + pluralize(wantedCount) + ":",
+ new LocationImpl(),
+ "But was " + pluralize(actualCount) + ". Undesired invocation:",
+ firstUndesired,
+ ""
+ );
+ }
+
+ public void neverWantedButInvoked(DescribedInvocation wanted, Location firstUndesired) {
+ throw new NeverWantedButInvoked(join(
+ wanted.toString(),
+ "Never wanted here:",
+ new LocationImpl(),
+ "But invoked here:",
+ firstUndesired,
+ ""
+ ));
+ }
+
+ public void tooManyActualInvocationsInOrder(int wantedCount, int actualCount, DescribedInvocation wanted, Location firstUndesired) {
+ String message = createTooManyInvocationsMessage(wantedCount, actualCount, wanted, firstUndesired);
+ throw new VerificationInOrderFailure(join(
+ "Verification in order failure:" + message
+ ));
+ }
+
+ private String createTooLittleInvocationsMessage(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted,
+ Location lastActualInvocation) {
+ String ending =
+ (lastActualInvocation != null)? lastActualInvocation + "\n" : "\n";
+
+ String message = join(
+ wanted.toString(),
+ "Wanted " + discrepancy.getPluralizedWantedCount() + ":",
+ new LocationImpl(),
+ "But was " + discrepancy.getPluralizedActualCount() + ":",
+ ending
+ );
+ return message;
+ }
+
+ public void tooLittleActualInvocations(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted, Location lastActualLocation) {
+ String message = createTooLittleInvocationsMessage(discrepancy, wanted, lastActualLocation);
+
+ throw new TooLittleActualInvocations(message);
+ }
+
+ public void tooLittleActualInvocationsInOrder(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted, Location lastActualLocation) {
+ String message = createTooLittleInvocationsMessage(discrepancy, wanted, lastActualLocation);
+
+ throw new VerificationInOrderFailure(join(
+ "Verification in order failure:" + message
+ ));
+ }
+
+ public void noMoreInteractionsWanted(Invocation undesired, List<VerificationAwareInvocation> invocations) {
+ ScenarioPrinter scenarioPrinter = new ScenarioPrinter();
+ String scenario = scenarioPrinter.print(invocations);
+
+ throw new NoInteractionsWanted(join(
+ "No interactions wanted here:",
+ new LocationImpl(),
+ "But found this interaction:",
+ undesired.getLocation(),
+ scenario
+ ));
+ }
+
+ public void noMoreInteractionsWantedInOrder(Invocation undesired) {
+ throw new VerificationInOrderFailure(join(
+ "No interactions wanted here:",
+ new LocationImpl(),
+ "But found this interaction:",
+ undesired.getLocation(),
+ ""
+ ));
+ }
+
+ public void cannotMockFinalClass(Class<?> clazz) {
+ throw new MockitoException(join(
+ "Cannot mock/spy " + clazz.toString(),
+ "Mockito cannot mock/spy following:",
+ " - final classes",
+ " - anonymous classes",
+ " - primitive types"
+ ));
+ }
+
+ public void cannotStubVoidMethodWithAReturnValue(String methodName) {
+ throw new MockitoException(join(
+ "'" + methodName + "' is a *void method* and it *cannot* be stubbed with a *return value*!",
+ "Voids are usually stubbed with Throwables:",
+ " doThrow(exception).when(mock).someVoidMethod();",
+ "***",
+ "If you're unsure why you're getting above error read on.",
+ "Due to the nature of the syntax above problem might occur because:",
+ "1. The method you are trying to stub is *overloaded*. Make sure you are calling the right overloaded version.",
+ "2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not verify/stub final methods.",
+ "3. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
+ " - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
+ ""
+ ));
+ }
+
+ public void onlyVoidMethodsCanBeSetToDoNothing() {
+ throw new MockitoException(join(
+ "Only void methods can doNothing()!",
+ "Example of correct use of doNothing():",
+ " doNothing().",
+ " doThrow(new RuntimeException())",
+ " .when(mock).someVoidMethod();",
+ "Above means:",
+ "someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called"
+ ));
+ }
+
+ public void wrongTypeOfReturnValue(String expectedType, String actualType, String methodName) {
+ throw new WrongTypeOfReturnValue(join(
+ actualType + " cannot be returned by " + methodName + "()",
+ methodName + "() should return " + expectedType,
+ "***",
+ "If you're unsure why you're getting above error read on.",
+ "Due to the nature of the syntax above problem might occur because:",
+ "1. This exception *might* occur in wrongly written multi-threaded tests.",
+ " Please refer to Mockito FAQ on limitations of concurrency testing.",
+ "2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
+ " - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
+ ""
+ ));
+ }
+
+ public void wantedAtMostX(int maxNumberOfInvocations, int foundSize) {
+ throw new MockitoAssertionError(join("Wanted at most " + pluralize(maxNumberOfInvocations) + " but was " + foundSize));
+ }
+
+ public void misplacedArgumentMatcher(List<LocalizedMatcher> lastMatchers) {
+ throw new InvalidUseOfMatchersException(join(
+ "Misplaced argument matcher detected here:",
+ locationsOf(lastMatchers),
+ "",
+ "You cannot use argument matchers outside of verification or stubbing.",
+ "Examples of correct usage of argument matchers:",
+ " when(mock.get(anyInt())).thenReturn(null);",
+ " doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());",
+ " verify(mock).someMethod(contains(\"foo\"))",
+ "",
+ "Also, this error might show up because you use argument matchers with methods that cannot be mocked.",
+ "Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().",
+ ""
+ ));
+ }
+
+ public void smartNullPointerException(String invocation, Location location) {
+ throw new SmartNullPointerException(join(
+ "You have a NullPointerException here:",
+ new LocationImpl(),
+ "because this method call was *not* stubbed correctly:",
+ location,
+ invocation,
+ ""
+ ));
+ }
+
+ public void noArgumentValueWasCaptured() {
+ throw new MockitoException(join(
+ "No argument value was captured!",
+ "You might have forgotten to use argument.capture() in verify()...",
+ "...or you used capture() in stubbing but stubbed method was not called.",
+ "Be aware that it is recommended to use capture() only with verify()",
+ "",
+ "Examples of correct argument capturing:",
+ " ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);",
+ " verify(mock).doSomething(argument.capture());",
+ " assertEquals(\"John\", argument.getValue().getName());",
+ ""
+ ));
+ }
+
+ public void extraInterfacesDoesNotAcceptNullParameters() {
+ throw new MockitoException(join(
+ "extraInterfaces() does not accept null parameters."
+ ));
+ }
+
+ public void extraInterfacesAcceptsOnlyInterfaces(Class<?> wrongType) {
+ throw new MockitoException(join(
+ "extraInterfaces() accepts only interfaces.",
+ "You passed following type: " + wrongType.getSimpleName() + " which is not an interface."
+ ));
+ }
+
+ public void extraInterfacesCannotContainMockedType(Class<?> wrongType) {
+ throw new MockitoException(join(
+ "extraInterfaces() does not accept the same type as the mocked type.",
+ "You mocked following type: " + wrongType.getSimpleName(),
+ "and you passed the same very interface to the extraInterfaces()"
+ ));
+ }
+
+ public void extraInterfacesRequiresAtLeastOneInterface() {
+ throw new MockitoException(join(
+ "extraInterfaces() requires at least one interface."
+ ));
+ }
+
+ public void mockedTypeIsInconsistentWithSpiedInstanceType(Class<?> mockedType, Object spiedInstance) {
+ throw new MockitoException(join(
+ "Mocked type must be the same as the type of your spied instance.",
+ "Mocked type must be: " + spiedInstance.getClass().getSimpleName() + ", but is: " + mockedType.getSimpleName(),
+ " //correct spying:",
+ " spy = mock( ->ArrayList.class<- , withSettings().spiedInstance( ->new ArrayList()<- );",
+ " //incorrect - types don't match:",
+ " spy = mock( ->List.class<- , withSettings().spiedInstance( ->new ArrayList()<- );"
+ ));
+ }
+
+ public void cannotCallRealMethodOnInterface() {
+ throw new MockitoException(join(
+ "Cannot call real method on java interface. Interface does not have any implementation!",
+ "Calling real methods is only possible when mocking concrete classes.",
+ " //correct example:",
+ " when(mockOfConcreteClass.doStuff()).thenCallRealMethod();"
+ ));
+ }
+
+ public void cannotVerifyToString() {
+ throw new MockitoException(join(
+ "Mockito cannot verify toString()",
+ "toString() is too often used behind of scenes (i.e. during String concatenation, in IDE debugging views). " +
+ "Verifying it may give inconsistent or hard to understand results. " +
+ "Not to mention that verifying toString() most likely hints awkward design (hard to explain in a short exception message. Trust me...)",
+ "However, it is possible to stub toString(). Stubbing toString() smells a bit funny but there are rare, legitimate use cases."
+ ));
+ }
+
+ public void moreThanOneAnnotationNotAllowed(String fieldName) {
+ throw new MockitoException("You cannot have more than one Mockito annotation on a field!\n" +
+ "The field '" + fieldName + "' has multiple Mockito annotations.\n" +
+ "For info how to use annotations see examples in javadoc for MockitoAnnotations class.");
+ }
+
+ public void unsupportedCombinationOfAnnotations(String undesiredAnnotationOne, String undesiredAnnotationTwo) {
+ throw new MockitoException("This combination of annotations is not permitted on a single field:\n" +
+ "@" + undesiredAnnotationOne + " and @" + undesiredAnnotationTwo);
+ }
+
+ public void cannotInitializeForSpyAnnotation(String fieldName, Exception details) {
+ throw new MockitoException(join("Cannot instantiate a @Spy for '" + fieldName + "' field.",
+ "You haven't provided the instance for spying at field declaration so I tried to construct the instance.",
+ "However, I failed because: " + details.getMessage(),
+ "Examples of correct usage of @Spy:",
+ " @Spy List mock = new LinkedList();",
+ " @Spy Foo foo; //only if Foo has parameterless constructor",
+ " //also, don't forget about MockitoAnnotations.initMocks();",
+ ""), details);
+ }
+
+ public void cannotInitializeForInjectMocksAnnotation(String fieldName, Exception details) {
+ throw new MockitoException(join("Cannot instantiate @InjectMocks field named '" + fieldName + "'.",
+ "You haven't provided the instance at field declaration so I tried to construct the instance.",
+ "However, I failed because: " + details.getMessage(),
+ "Examples of correct usage of @InjectMocks:",
+ " @InjectMocks Service service = new Service();",
+ " @InjectMocks Service service;",
+ " //also, don't forget about MockitoAnnotations.initMocks();",
+ " //and... don't forget about some @Mocks for injection :)",
+ ""), details);
+ }
+
+ public void atMostShouldNotBeUsedWithTimeout() {
+ throw new FriendlyReminderException(join("",
+ "Don't panic! I'm just a friendly reminder!",
+ "timeout() should not be used with atMost() because...",
+ "...it does not make much sense - the test would have passed immediately in concurency",
+ "We kept this method only to avoid compilation errors when upgrading Mockito.",
+ "In future release we will remove timeout(x).atMost(y) from the API.",
+ "If you want to find out more please refer to issue 235",
+ ""));
+ }
+
+ public void fieldInitialisationThrewException(Field field, Throwable details) {
+ throw new MockitoException(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(),
+ ""), details);
+
+ }
+
+ public void invocationListenerDoesNotAcceptNullParameters() {
+ throw new MockitoException("invocationListeners() does not accept null parameters");
+ }
+
+ public void invocationListenersRequiresAtLeastOneListener() {
+ throw new MockitoException("invocationListeners() requires at least one listener");
+ }
+
+ public void invocationListenerThrewException(InvocationListener listener, Throwable listenerThrowable) {
+ throw new MockitoException(StringJoiner.join(
+ "The invocation listener with type " + listener.getClass().getName(),
+ "threw an exception : " + listenerThrowable.getClass().getName() + listenerThrowable.getMessage()), listenerThrowable);
+ }
+
+ public void cannotInjectDependency(Field field, Object matchingMock, Exception details) {
+ throw new MockitoException(join(
+ "Mockito couldn't inject mock dependency '" + new MockUtil().getMockName(matchingMock) + "' on field ",
+ "'" + field + "'",
+ "whose type '" + field.getDeclaringClass().getCanonicalName() + "' was annotated by @InjectMocks in your test.",
+ "Also I failed because: " + details.getCause().getMessage(),
+ ""
+ ), details);
+ }
+
+ public void mockedTypeIsInconsistentWithDelegatedInstanceType(Class mockedType, Object delegatedInstance) {
+ throw new MockitoException(join(
+ "Mocked type must be the same as the type of your delegated instance.",
+ "Mocked type must be: " + delegatedInstance.getClass().getSimpleName() + ", but is: " + mockedType.getSimpleName(),
+ " //correct delegate:",
+ " spy = mock( ->List.class<- , withSettings().delegatedInstance( ->new ArrayList()<- );",
+ " //incorrect - types don't match:",
+ " spy = mock( ->List.class<- , withSettings().delegatedInstance( ->new HashSet()<- );"
+ ));
+ }
+
+ public void spyAndDelegateAreMutuallyExclusive() {
+ throw new MockitoException(join(
+ "Settings should not define a spy instance and a delegated instance at the same time."
+ )) ;
+ }
+
+ public void invalidArgumentRangeAtIdentityAnswerCreationTime() {
+ throw new MockitoException(join("Invalid argument index.",
+ "The index need to be a positive number that indicates the position of the argument to return.",
+ "However it is possible to use the -1 value to indicates that the last argument should be",
+ "returned."));
+ }
+
+ public int invalidArgumentPositionRangeAtInvocationTime(InvocationOnMock invocation, boolean willReturnLastParameter, int argumentIndex) {
+ throw new MockitoException(
+ join("Invalid argument index for the current invocation of method : ",
+ " -> " + new MockUtil().getMockName(invocation.getMock()) + "." + invocation.getMethod().getName() + "()",
+ "",
+ (willReturnLastParameter ?
+ "Last parameter wanted" :
+ "Wanted parameter at position " + argumentIndex) + " but " + possibleArgumentTypesOf(invocation),
+ "The index need to be a positive number that indicates a valid position of the argument in the invocation.",
+ "However it is possible to use the -1 value to indicates that the last argument should be returned.",
+ ""));
+ }
+
+ private StringBuilder possibleArgumentTypesOf(InvocationOnMock invocation) {
+ Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
+ if (parameterTypes.length == 0) {
+ return new StringBuilder("the method has no arguments.\n");
+ }
+
+ StringBuilder stringBuilder = new StringBuilder("the possible argument indexes for this method are :\n");
+ for (int i = 0, parameterTypesLength = parameterTypes.length; i < parameterTypesLength; i++) {
+ stringBuilder.append(" [").append(i);
+
+ if (invocation.getMethod().isVarArgs() && i == parameterTypesLength - 1) {
+ stringBuilder.append("+] ").append(parameterTypes[i].getComponentType().getSimpleName()).append(" <- Vararg").append("\n");
+ } else {
+ stringBuilder.append("] ").append(parameterTypes[i].getSimpleName()).append("\n");
+ }
+ }
+ return stringBuilder;
+ }
+
+ public void wrongTypeOfArgumentToReturn(InvocationOnMock invocation, String expectedType, Class actualType, int argumentIndex) {
+ throw new WrongTypeOfReturnValue(join(
+ "The argument of type '" + actualType.getSimpleName() + "' cannot be returned because the following ",
+ "method should return the type '" + expectedType + "'",
+ " -> " + new MockUtil().getMockName(invocation.getMock()) + "." + invocation.getMethod().getName() + "()",
+ "",
+ "The reason for this error can be :",
+ "1. The wanted argument position is incorrect.",
+ "2. The answer is used on the wrong interaction.",
+ "",
+ "Position of the wanted argument is " + argumentIndex + " and " + possibleArgumentTypesOf(invocation),
+ "***",
+ "However if you're still unsure why you're getting above error read on.",
+ "Due to the nature of the syntax above problem might occur because:",
+ "1. This exception *might* occur in wrongly written multi-threaded tests.",
+ " Please refer to Mockito FAQ on limitations of concurrency testing.",
+ "2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
+ " - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
+ ""
+ ));
+ }
+
+ public void defaultAnswerDoesNotAcceptNullParameter() {
+ throw new MockitoException("defaultAnswer() does not accept null parameter");
+ }
+
+ public void serializableWontWorkForObjectsThatDontImplementSerializable(Class classToMock) {
+ throw new MockitoException(join(
+ "You are using the setting 'withSettings().serializable()' however the type you are trying to mock '" + classToMock.getSimpleName() + "'",
+ "do not implement Serializable AND do not have a no-arg constructor.",
+ "This combination is requested, otherwise you will get an 'java.io.InvalidClassException' when the mock will be serialized",
+ "",
+ "Also note that as requested by the Java serialization specification, the whole hierarchy need to implements Serializable,",
+ "i.e. the top-most superclass has to implements Serializable.",
+ ""
+ ));
+ }
+}
diff --git a/src/org/mockito/exceptions/base/MockitoAssertionError.java b/src/org/mockito/exceptions/base/MockitoAssertionError.java
new file mode 100644
index 0000000..172601e
--- /dev/null
+++ b/src/org/mockito/exceptions/base/MockitoAssertionError.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+
+
+
+public class MockitoAssertionError extends AssertionError {
+
+ private static final long serialVersionUID = 1L;
+ private StackTraceElement[] unfilteredStackTrace;
+
+ public MockitoAssertionError(String message) {
+ super(message);
+
+ unfilteredStackTrace = getStackTrace();
+
+ ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
+ filter.filter(this);
+ }
+
+ public StackTraceElement[] getUnfilteredStackTrace() {
+ return unfilteredStackTrace;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/base/MockitoException.java b/src/org/mockito/exceptions/base/MockitoException.java
new file mode 100644
index 0000000..3aa4362
--- /dev/null
+++ b/src/org/mockito/exceptions/base/MockitoException.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+
+
+/**
+ * Raised by mockito to emit an error either due to Mockito, or due to the User.
+ *
+ * <p>
+ * The stack trace is filtered from mockito calls if you are using {@link #getStackTrace()}.
+ * For debugging purpose though you can still access the full stacktrace using {@link #getUnfilteredStackTrace()}.
+ * However note that other calls related to the stackTrace will refer to the filter stacktrace.
+ * </p>
+ *
+ */
+public class MockitoException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ private StackTraceElement[] unfilteredStackTrace;
+
+ // TODO lazy filtered stacktrace initialization
+ public MockitoException(String message, Throwable t) {
+ super(message, t);
+ filterStackTrace();
+ }
+
+ public MockitoException(String message) {
+ super(message);
+ filterStackTrace();
+ }
+
+ private void filterStackTrace() {
+ unfilteredStackTrace = getStackTrace();
+
+ ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
+ filter.filter(this);
+ }
+
+ public StackTraceElement[] getUnfilteredStackTrace() {
+ return unfilteredStackTrace;
+ }
+}
diff --git a/src/org/mockito/exceptions/base/MockitoSerializationIssue.java b/src/org/mockito/exceptions/base/MockitoSerializationIssue.java
new file mode 100644
index 0000000..b25a431
--- /dev/null
+++ b/src/org/mockito/exceptions/base/MockitoSerializationIssue.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.base;
+
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+
+import java.io.ObjectStreamException;
+
+/**
+ * Raised by mockito to emit an error either due to Mockito, or due to the User.
+ *
+ * <p>
+ * The stack trace is filtered from mockito calls if you are using {@link #getStackTrace()}.
+ * For debugging purpose though you can still access the full stacktrace using {@link #getUnfilteredStackTrace()}.
+ * However note that other calls related to the stackTrace will refer to the filter stacktrace.
+ * </p>
+ *
+ * @since 1.9.6
+ */
+public class MockitoSerializationIssue extends ObjectStreamException {
+
+ private StackTraceElement[] unfilteredStackTrace;
+
+ public MockitoSerializationIssue(String message, Exception cause) {
+ super(message);
+ initCause(cause);
+ filterStackTrace();
+ }
+
+ @Override
+ public StackTraceElement[] getStackTrace() {
+ filterStackTrace();
+ return super.getStackTrace();
+ }
+
+ private void filterStackTrace() {
+ unfilteredStackTrace = super.getStackTrace();
+
+ ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
+ filter.filter(this);
+ }
+
+ public StackTraceElement[] getUnfilteredStackTrace() {
+ return unfilteredStackTrace;
+ }
+}
diff --git a/src/org/mockito/exceptions/base/package.html b/src/org/mockito/exceptions/base/package.html
new file mode 100644
index 0000000..4f07e45
--- /dev/null
+++ b/src/org/mockito/exceptions/base/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Base classes for exceptions and errors, stack trace filtering/removing logic.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/misusing/CannotVerifyStubOnlyMock.java b/src/org/mockito/exceptions/misusing/CannotVerifyStubOnlyMock.java
new file mode 100644
index 0000000..2c8a656
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/CannotVerifyStubOnlyMock.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class CannotVerifyStubOnlyMock extends MockitoException {
+
+ public CannotVerifyStubOnlyMock(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/misusing/FriendlyReminderException.java b/src/org/mockito/exceptions/misusing/FriendlyReminderException.java
new file mode 100644
index 0000000..1201890
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/FriendlyReminderException.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class FriendlyReminderException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public FriendlyReminderException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java b/src/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java
new file mode 100644
index 0000000..64623a3
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class InvalidUseOfMatchersException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public InvalidUseOfMatchersException(String message) {
+ super(message);
+ }
+
+ public InvalidUseOfMatchersException() {
+ super("");
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/misusing/MissingMethodInvocationException.java b/src/org/mockito/exceptions/misusing/MissingMethodInvocationException.java
new file mode 100644
index 0000000..ae77fb0
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/MissingMethodInvocationException.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class MissingMethodInvocationException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public MissingMethodInvocationException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/misusing/MockitoConfigurationException.java b/src/org/mockito/exceptions/misusing/MockitoConfigurationException.java
new file mode 100644
index 0000000..ae39427
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/MockitoConfigurationException.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class MockitoConfigurationException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public MockitoConfigurationException(String message) {
+ super(message);
+ }
+
+ public MockitoConfigurationException(String message, Exception cause) {
+ super(message, cause);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/misusing/NotAMockException.java b/src/org/mockito/exceptions/misusing/NotAMockException.java
new file mode 100644
index 0000000..d4fb917
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/NotAMockException.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class NotAMockException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public NotAMockException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/misusing/NullInsteadOfMockException.java b/src/org/mockito/exceptions/misusing/NullInsteadOfMockException.java
new file mode 100644
index 0000000..5225f7c
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/NullInsteadOfMockException.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class NullInsteadOfMockException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public NullInsteadOfMockException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/misusing/UnfinishedStubbingException.java b/src/org/mockito/exceptions/misusing/UnfinishedStubbingException.java
new file mode 100644
index 0000000..3085161
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/UnfinishedStubbingException.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class UnfinishedStubbingException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public UnfinishedStubbingException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/misusing/UnfinishedVerificationException.java b/src/org/mockito/exceptions/misusing/UnfinishedVerificationException.java
new file mode 100644
index 0000000..3d06840
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/UnfinishedVerificationException.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class UnfinishedVerificationException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public UnfinishedVerificationException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java b/src/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java
new file mode 100644
index 0000000..46acc77
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2007 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;
+
+public class WrongTypeOfReturnValue extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public WrongTypeOfReturnValue(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/misusing/package.html b/src/org/mockito/exceptions/misusing/package.html
new file mode 100644
index 0000000..64bfbc5
--- /dev/null
+++ b/src/org/mockito/exceptions/misusing/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Exceptions thrown when Mockito is misused.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/package.html b/src/org/mockito/exceptions/package.html
new file mode 100644
index 0000000..a2e03c3
--- /dev/null
+++ b/src/org/mockito/exceptions/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Exception messages, exception hierarchies.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/stacktrace/StackTraceCleaner.java b/src/org/mockito/exceptions/stacktrace/StackTraceCleaner.java
new file mode 100644
index 0000000..8e728ac
--- /dev/null
+++ b/src/org/mockito/exceptions/stacktrace/StackTraceCleaner.java
@@ -0,0 +1,29 @@
+package org.mockito.exceptions.stacktrace;
+
+import org.mockito.Incubating;
+
+/**
+ * Decides if particular StackTraceElement is excluded from the human-readable stack trace output.
+ * Mockito stack trace filtering mechanism uses this information.
+ * <p>
+ * Excluding an element will make it not show in the cleaned stack trace.
+ * Not-excluding an element does not guarantee it will be shown
+ * (e.g. it depends on the implementation of
+ * Mockito internal {@link org.mockito.internal.exceptions.stacktrace.StackTraceFilter}).
+ * <p>
+ * The implementations are required to be thread safe. For example, make them stateless.
+ * <p>
+ * See the default implementation: {@link org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleaner}.
+ *
+ */
+@Incubating
+public interface StackTraceCleaner {
+
+ /**
+ * Decides if element is excluded.
+ *
+ * @param candidate element of the actual stack trace
+ * @return whether the element should be excluded from cleaned stack trace.
+ */
+ boolean isOut(StackTraceElement candidate);
+}
diff --git a/src/org/mockito/exceptions/stacktrace/package.html b/src/org/mockito/exceptions/stacktrace/package.html
new file mode 100644
index 0000000..2251473
--- /dev/null
+++ b/src/org/mockito/exceptions/stacktrace/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Stack trace filtering / cleaning public APIs.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/verification/ArgumentsAreDifferent.java b/src/org/mockito/exceptions/verification/ArgumentsAreDifferent.java
new file mode 100644
index 0000000..41d01bb
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/ArgumentsAreDifferent.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.util.RemoveFirstLine;
+
+public class ArgumentsAreDifferent extends MockitoAssertionError {
+
+ private static final long serialVersionUID = 1L;
+
+ public ArgumentsAreDifferent(String message) {
+ super(message);
+ }
+
+ @Override
+ public String toString() {
+ return new RemoveFirstLine().of(super.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/verification/NeverWantedButInvoked.java b/src/org/mockito/exceptions/verification/NeverWantedButInvoked.java
new file mode 100644
index 0000000..e8e3ba9
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/NeverWantedButInvoked.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+
+public class NeverWantedButInvoked extends MockitoAssertionError {
+
+ private static final long serialVersionUID = 1L;
+
+ public NeverWantedButInvoked(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/verification/NoInteractionsWanted.java b/src/org/mockito/exceptions/verification/NoInteractionsWanted.java
new file mode 100644
index 0000000..e1aafb5
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/NoInteractionsWanted.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+
+/**
+ * No interactions wanted. See exception's cause for location of undesired invocation.
+ */
+public class NoInteractionsWanted extends MockitoAssertionError {
+
+ private static final long serialVersionUID = 1L;
+
+ public NoInteractionsWanted(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/verification/SmartNullPointerException.java b/src/org/mockito/exceptions/verification/SmartNullPointerException.java
new file mode 100644
index 0000000..c1f7f0f
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/SmartNullPointerException.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoException;
+
+public class SmartNullPointerException extends MockitoException {
+
+ private static final long serialVersionUID = 1L;
+
+ public SmartNullPointerException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/verification/TooLittleActualInvocations.java b/src/org/mockito/exceptions/verification/TooLittleActualInvocations.java
new file mode 100644
index 0000000..01af460
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/TooLittleActualInvocations.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+
+public class TooLittleActualInvocations extends MockitoAssertionError {
+
+ private static final long serialVersionUID = 1L;
+
+ public TooLittleActualInvocations(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/verification/TooManyActualInvocations.java b/src/org/mockito/exceptions/verification/TooManyActualInvocations.java
new file mode 100644
index 0000000..e29ec7a
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/TooManyActualInvocations.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+
+public class TooManyActualInvocations extends MockitoAssertionError {
+
+ private static final long serialVersionUID = 1L;
+
+ public TooManyActualInvocations(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/verification/VerificationInOrderFailure.java b/src/org/mockito/exceptions/verification/VerificationInOrderFailure.java
new file mode 100644
index 0000000..d27c30c
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/VerificationInOrderFailure.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+
+public class VerificationInOrderFailure extends MockitoAssertionError {
+
+ private static final long serialVersionUID = 1L;
+
+ public VerificationInOrderFailure(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/mockito/exceptions/verification/WantedButNotInvoked.java b/src/org/mockito/exceptions/verification/WantedButNotInvoked.java
new file mode 100644
index 0000000..007d70c
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/WantedButNotInvoked.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.util.RemoveFirstLine;
+
+public class WantedButNotInvoked extends MockitoAssertionError {
+
+ private static final long serialVersionUID = 1L;
+
+ public WantedButNotInvoked(String message) {
+ super(message);
+ }
+
+ @Override
+ public String toString() {
+ return new RemoveFirstLine().of(super.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java b/src/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java
new file mode 100644
index 0000000..4eb9ea6
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.exceptions.verification.junit;
+
+import junit.framework.ComparisonFailure;
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+import org.mockito.internal.util.RemoveFirstLine;
+
+
+public class ArgumentsAreDifferent extends ComparisonFailure {
+
+ private static final long serialVersionUID = 1L;
+ private final String message;
+ private StackTraceElement[] unfilteredStackTrace;
+
+ public ArgumentsAreDifferent(String message, String wanted, String actual) {
+ super(message, wanted, actual);
+ this.message = message;
+
+ unfilteredStackTrace = getStackTrace();
+ ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
+ filter.filter(this);
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ public StackTraceElement[] getUnfilteredStackTrace() {
+ return unfilteredStackTrace;
+ }
+
+ @Override
+ public String toString() {
+ return new RemoveFirstLine().of(super.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/verification/junit/JUnitTool.java b/src/org/mockito/exceptions/verification/junit/JUnitTool.java
new file mode 100644
index 0000000..70af301
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/junit/JUnitTool.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.exceptions.verification.junit;
+
+@Deprecated
+/**
+ * @Deprecated. This class has been moved to internal packages because it was never meant to be public.
+ * If you need it for extending Mockito please let us know. You can still use {@link org.mockito.internal.junit.JUnitTool}.
+ * However, the package clearly states that the class in a part of a public API so it can change.
+ */
+public class JUnitTool {
+
+ public static boolean hasJUnit() {
+ return org.mockito.internal.junit.JUnitTool.hasJUnit();
+ }
+
+ public static AssertionError createArgumentsAreDifferentException(String message, String wanted, String actual) {
+ return org.mockito.internal.junit.JUnitTool.createArgumentsAreDifferentException(message, wanted, actual);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/verification/junit/package.html b/src/org/mockito/exceptions/verification/junit/package.html
new file mode 100644
index 0000000..4b1a32e
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/junit/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+JUnit integration to provide better support for junit runners in IDEs.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/exceptions/verification/package.html b/src/org/mockito/exceptions/verification/package.html
new file mode 100644
index 0000000..6471a75
--- /dev/null
+++ b/src/org/mockito/exceptions/verification/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Verification errors.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/InOrderImpl.java b/src/org/mockito/internal/InOrderImpl.java
new file mode 100644
index 0000000..0a2808f
--- /dev/null
+++ b/src/org/mockito/internal/InOrderImpl.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.mockito.InOrder;
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.verification.InOrderContextImpl;
+import org.mockito.internal.verification.InOrderWrapper;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.internal.verification.api.VerificationInOrderMode;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+/**
+ * Allows verifying in order. This class should not be exposed, hence default access.
+ */
+public class InOrderImpl implements InOrder, InOrderContext {
+
+ private final MockitoCore mockitoCore = new MockitoCore();
+ private final Reporter reporter = new Reporter();
+ private final List<Object> mocksToBeVerifiedInOrder = new LinkedList<Object>();
+ private final InOrderContext inOrderContext = new InOrderContextImpl();
+
+ public List<Object> getMocksToBeVerifiedInOrder() {
+ return mocksToBeVerifiedInOrder;
+ }
+
+ public InOrderImpl(List<Object> mocksToBeVerifiedInOrder) {
+ this.mocksToBeVerifiedInOrder.addAll(mocksToBeVerifiedInOrder);
+ }
+
+ public <T> T verify(T mock) {
+ return this.verify(mock, VerificationModeFactory.times(1));
+ }
+
+ public <T> T verify(T mock, VerificationMode mode) {
+ if (!mocksToBeVerifiedInOrder.contains(mock)) {
+ reporter.inOrderRequiresFamiliarMock();
+ } else if (!(mode instanceof VerificationInOrderMode)) {
+ throw new MockitoException(mode.getClass().getSimpleName() + " is not implemented to work with InOrder");
+ }
+ return mockitoCore.verify(mock, new InOrderWrapper((VerificationInOrderMode) mode, this));
+ }
+
+ public boolean isVerified(Invocation i) {
+ return inOrderContext.isVerified(i);
+ }
+
+ public void markVerified(Invocation i) {
+ inOrderContext.markVerified(i);
+ }
+
+ public void verifyNoMoreInteractions() {
+ mockitoCore.verifyNoMoreInteractionsInOrder(mocksToBeVerifiedInOrder, this);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/InternalMockHandler.java b/src/org/mockito/internal/InternalMockHandler.java
new file mode 100644
index 0000000..8bed989
--- /dev/null
+++ b/src/org/mockito/internal/InternalMockHandler.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal;
+
+import java.util.List;
+
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.VoidMethodStubbable;
+
+@SuppressWarnings("unchecked")
+public interface InternalMockHandler<T> extends MockHandler {
+
+ MockCreationSettings getMockSettings();
+
+ VoidMethodStubbable<T> voidMethodStubbable(T mock);
+
+ void setAnswersForStubbing(List<Answer> answers);
+
+ InvocationContainer getInvocationContainer();
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/MockitoCore.java b/src/org/mockito/internal/MockitoCore.java
new file mode 100755
index 0000000..49107b8
--- /dev/null
+++ b/src/org/mockito/internal/MockitoCore.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal;
+
+import org.mockito.InOrder;
+import org.mockito.MockSettings;
+import org.mockito.MockingDetails;
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.invocation.finder.VerifiableInvocationsFinder;
+import org.mockito.internal.progress.IOngoingStubbing;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.stubbing.OngoingStubbingImpl;
+import org.mockito.internal.stubbing.StubberImpl;
+import org.mockito.internal.util.DefaultMockingDetails;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.verification.MockAwareVerificationMode;
+import org.mockito.internal.verification.VerificationDataImpl;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.internal.verification.api.VerificationDataInOrder;
+import org.mockito.internal.verification.api.VerificationDataInOrderImpl;
+import org.mockito.invocation.Invocation;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.*;
+import org.mockito.verification.VerificationMode;
+
+import java.util.Arrays;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class MockitoCore {
+
+ private final Reporter reporter = new Reporter();
+ private final MockUtil mockUtil = new MockUtil();
+ private final MockingProgress mockingProgress = new ThreadSafeMockingProgress();
+
+ public boolean isTypeMockable(Class<?> typeToMock) {
+ return mockUtil.isTypeMockable(typeToMock);
+ }
+
+ public <T> T mock(Class<T> typeToMock, MockSettings settings) {
+ if (!MockSettingsImpl.class.isInstance(settings)) {
+ throw new IllegalArgumentException(
+ "Unexpected implementation of '" + settings.getClass().getCanonicalName() + "'\n"
+ + "At the moment, you cannot provide your own implementations that class.");
+ }
+ MockSettingsImpl impl = MockSettingsImpl.class.cast(settings);
+ MockCreationSettings<T> creationSettings = impl.confirm(typeToMock);
+ T mock = mockUtil.createMock(creationSettings);
+ mockingProgress.mockingStarted(mock, typeToMock);
+ return mock;
+ }
+
+ public IOngoingStubbing stub() {
+ IOngoingStubbing stubbing = mockingProgress.pullOngoingStubbing();
+ if (stubbing == null) {
+ mockingProgress.reset();
+ reporter.missingMethodInvocation();
+ }
+ return stubbing;
+ }
+
+ public <T> DeprecatedOngoingStubbing<T> stub(T methodCall) {
+ mockingProgress.stubbingStarted();
+ return (DeprecatedOngoingStubbing) stub();
+ }
+
+ public <T> OngoingStubbing<T> when(T methodCall) {
+ mockingProgress.stubbingStarted();
+ return (OngoingStubbing) stub();
+ }
+
+ public <T> T verify(T mock, VerificationMode mode) {
+ if (mock == null) {
+ reporter.nullPassedToVerify();
+ } else if (!mockUtil.isMock(mock)) {
+ reporter.notAMockPassedToVerify(mock.getClass());
+ }
+ mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, mode));
+ return mock;
+ }
+
+ public <T> void reset(T ... mocks) {
+ mockingProgress.validateState();
+ mockingProgress.reset();
+ mockingProgress.resetOngoingStubbing();
+
+ for (T m : mocks) {
+ mockUtil.resetMock(m);
+ }
+ }
+
+ public void verifyNoMoreInteractions(Object... mocks) {
+ assertMocksNotEmpty(mocks);
+ mockingProgress.validateState();
+ for (Object mock : mocks) {
+ try {
+ if (mock == null) {
+ reporter.nullPassedToVerifyNoMoreInteractions();
+ }
+ InvocationContainer invocations = mockUtil.getMockHandler(mock).getInvocationContainer();
+ VerificationDataImpl data = new VerificationDataImpl(invocations, null);
+ VerificationModeFactory.noMoreInteractions().verify(data);
+ } catch (NotAMockException e) {
+ reporter.notAMockPassedToVerifyNoMoreInteractions();
+ }
+ }
+ }
+
+ public void verifyNoMoreInteractionsInOrder(List<Object> mocks, InOrderContext inOrderContext) {
+ mockingProgress.validateState();
+ VerifiableInvocationsFinder finder = new VerifiableInvocationsFinder();
+ VerificationDataInOrder data = new VerificationDataInOrderImpl(inOrderContext, finder.find(mocks), null);
+ VerificationModeFactory.noMoreInteractions().verifyInOrder(data);
+ }
+
+ private void assertMocksNotEmpty(Object[] mocks) {
+ if (mocks == null || mocks.length == 0) {
+ reporter.mocksHaveToBePassedToVerifyNoMoreInteractions();
+ }
+ }
+
+ public InOrder inOrder(Object... mocks) {
+ if (mocks == null || mocks.length == 0) {
+ reporter.mocksHaveToBePassedWhenCreatingInOrder();
+ }
+ for (Object mock : mocks) {
+ if (mock == null) {
+ reporter.nullPassedWhenCreatingInOrder();
+ } else if (!mockUtil.isMock(mock)) {
+ reporter.notAMockPassedWhenCreatingInOrder();
+ }
+ }
+ return new InOrderImpl(Arrays.asList(mocks));
+ }
+
+ public Stubber doAnswer(Answer answer) {
+ mockingProgress.stubbingStarted();
+ mockingProgress.resetOngoingStubbing();
+ return new StubberImpl().doAnswer(answer);
+ }
+
+ public <T> VoidMethodStubbable<T> stubVoid(T mock) {
+ InternalMockHandler<T> handler = mockUtil.getMockHandler(mock);
+ mockingProgress.stubbingStarted();
+ return handler.voidMethodStubbable(mock);
+ }
+
+ public void validateMockitoUsage() {
+ mockingProgress.validateState();
+ }
+
+ /**
+ * For testing purposes only. Is not the part of main API.
+ * @return last invocation
+ */
+ public Invocation getLastInvocation() {
+ OngoingStubbingImpl ongoingStubbing = ((OngoingStubbingImpl) mockingProgress.pullOngoingStubbing());
+ List<Invocation> allInvocations = ongoingStubbing.getRegisteredInvocations();
+ return allInvocations.get(allInvocations.size()-1);
+ }
+
+ public Object[] ignoreStubs(Object... mocks) {
+ for (Object m : mocks) {
+ InvocationContainer invocationContainer = new MockUtil().getMockHandler(m).getInvocationContainer();
+ List<Invocation> ins = invocationContainer.getInvocations();
+ for (Invocation in : ins) {
+ if (in.stubInfo() != null) {
+ in.ignoreForVerification();
+ }
+ }
+ }
+ return mocks;
+ }
+
+ public MockingDetails mockingDetails(Object toInspect) {
+ return new DefaultMockingDetails(toInspect, new MockUtil());
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/configuration/CaptorAnnotationProcessor.java b/src/org/mockito/internal/configuration/CaptorAnnotationProcessor.java
new file mode 100644
index 0000000..60b8dd8
--- /dev/null
+++ b/src/org/mockito/internal/configuration/CaptorAnnotationProcessor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.reflection.GenericMaster;
+
+import java.lang.reflect.Field;
+
+/**
+ * Instantiate {@link ArgumentCaptor} a field annotated by @Captor.
+ */
+public class CaptorAnnotationProcessor implements FieldAnnotationProcessor<Captor> {
+ public Object process(Captor annotation, Field field) {
+ Class<?> type = field.getType();
+ if (!ArgumentCaptor.class.isAssignableFrom(type)) {
+ throw new MockitoException("@Captor field must be of the type ArgumentCaptor.\n" + "Field: '"
+ + field.getName() + "' has wrong type\n"
+ + "For info how to use @Captor annotations see examples in javadoc for MockitoAnnotations class.");
+ }
+ Class cls = new GenericMaster().getGenericType(field);
+ return ArgumentCaptor.forClass(cls);
+ }
+}
diff --git a/src/org/mockito/internal/configuration/ClassPathLoader.java b/src/org/mockito/internal/configuration/ClassPathLoader.java
new file mode 100644
index 0000000..43b781b
--- /dev/null
+++ b/src/org/mockito/internal/configuration/ClassPathLoader.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.configuration.IMockitoConfiguration;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.exceptions.misusing.MockitoConfigurationException;
+import org.mockito.plugins.MockMaker;
+import org.mockito.plugins.StackTraceCleanerProvider;
+
+import java.io.*;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * Loads configuration or extension points available in the classpath.
+ *
+ * <p>
+ * <ul>
+ * <li>
+ * Can load the mockito configuration. The user who want to provide his own mockito configuration
+ * should write the class <code>org.mockito.configuration.MockitoConfiguration</code> that implements
+ * {@link IMockitoConfiguration}. For example :
+ * <pre class="code"><code class="java">
+ * package org.mockito.configuration;
+ *
+ * //...
+ *
+ * public class MockitoConfiguration implements IMockitoConfiguration {
+ * boolean enableClassCache() { return false; }
+ *
+ * // ...
+ * }
+ * </code></pre>
+ * </li>
+ * <li>
+ * Can load available mockito extensions. Currently Mockito only have one extension point the
+ * {@link MockMaker}. This extension point allows a user to provide his own bytecode engine to build mocks.
+ * <br>Suppose you wrote an extension to create mocks with some <em>Awesome</em> library, in order to tell
+ * Mockito to use it you need to put in your classpath
+ * <ol style="list-style-type: lower-alpha">
+ * <li>The implementation itself, for example <code>org.awesome.mockito.AwesomeMockMaker</code>.</li>
+ * <li>A file named <code>org.mockito.plugins.MockMaker</code> in a folder named
+ * <code>mockito-extensions</code>, the content of this file need to have <strong>one</strong> line with
+ * the qualified name <code>org.awesome.mockito.AwesomeMockMaker</code>.</li>
+ * </ol>
+ * </li>
+ * </ul>
+ * </p>
+ */
+public class ClassPathLoader {
+ private static final String DEFAULT_MOCK_MAKER_CLASS =
+ "org.mockito.internal.creation.CglibMockMaker";
+ private static final String DEFAULT_STACK_TRACE_CLEANER_PROVIDER_CLASS =
+ "org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleanerProvider";
+ public static final String MOCKITO_CONFIGURATION_CLASS_NAME = "org.mockito.configuration.MockitoConfiguration";
+
+ private static final MockMaker mockMaker = findPlatformMockMaker();
+ private static final StackTraceCleanerProvider stackTraceCleanerProvider =
+ findPlatformStackTraceCleanerProvider();
+
+ /**
+ * @return configuration loaded from classpath or null
+ */
+ @SuppressWarnings({"unchecked"})
+ public IMockitoConfiguration loadConfiguration() {
+ //Trying to get config from classpath
+ Class configClass;
+ try {
+ configClass = (Class) Class.forName(MOCKITO_CONFIGURATION_CLASS_NAME);
+ } catch (ClassNotFoundException e) {
+ //that's ok, it means there is no global config, using default one.
+ return null;
+ }
+
+ try {
+ return (IMockitoConfiguration) configClass.newInstance();
+ } catch (ClassCastException e) {
+ throw new MockitoConfigurationException("MockitoConfiguration class must implement " + IMockitoConfiguration.class.getName() + " interface.", e);
+ } catch (Exception e) {
+ throw new MockitoConfigurationException("Unable to instantiate " + MOCKITO_CONFIGURATION_CLASS_NAME +" class. Does it have a safe, no-arg constructor?", e);
+ }
+ }
+
+ /**
+ * Returns the implementation of the mock maker available for the current runtime.
+ *
+ * <p>Returns {@link org.mockito.internal.creation.CglibMockMaker} if no
+ * {@link MockMaker} extension exists or is visible in the current classpath.</p>
+ */
+ public static MockMaker getMockMaker() {
+ return mockMaker;
+ }
+
+ public static StackTraceCleanerProvider getStackTraceCleanerProvider() {
+ //TODO we should throw some sensible exception if this is null.
+ return stackTraceCleanerProvider;
+ }
+
+ /**
+ * Scans the classpath to find a mock maker plugin if one is available,
+ * allowing mockito to run on alternative platforms like Android.
+ */
+ static MockMaker findPlatformMockMaker() {
+ return findPluginImplementation(MockMaker.class, DEFAULT_MOCK_MAKER_CLASS);
+ }
+
+ static StackTraceCleanerProvider findPlatformStackTraceCleanerProvider() {
+ return findPluginImplementation(
+ StackTraceCleanerProvider.class, DEFAULT_STACK_TRACE_CLEANER_PROVIDER_CLASS);
+ }
+
+ static <T> T findPluginImplementation(Class<T> pluginType, String defaultPluginClassName) {
+ for (T plugin : loadImplementations(pluginType)) {
+ return plugin; // return the first one service loader finds (if any)
+ }
+
+ try {
+ // Default implementation. Use our own ClassLoader instead of the context
+ // ClassLoader, as the default implementation is assumed to be part of
+ // Mockito and may not be available via the context ClassLoader.
+ return pluginType.cast(Class.forName(defaultPluginClassName).newInstance());
+ } catch (Exception e) {
+ throw new MockitoException("Internal problem occurred, please report it. " +
+ "Mockito is unable to load the default implementation of class that is a part of Mockito distribution. " +
+ "Failed to load " + pluginType, e);
+ }
+ }
+
+ /**
+ * Equivalent to {@link java.util.ServiceLoader#load} but without requiring
+ * Java 6 / Android 2.3 (Gingerbread).
+ */
+ static <T> List<T> loadImplementations(Class<T> service) {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ if (loader == null) {
+ loader = ClassLoader.getSystemClassLoader();
+ }
+ Enumeration<URL> resources;
+ try {
+ resources = loader.getResources("mockito-extensions/" + service.getName());
+ } catch (IOException e) {
+ throw new MockitoException("Failed to load " + service, e);
+ }
+
+ List<T> result = new ArrayList<T>();
+ for (URL resource : Collections.list(resources)) {
+ InputStream in = null;
+ try {
+ in = resource.openStream();
+ for (String line : readerToLines(new InputStreamReader(in, "UTF-8"))) {
+ String name = stripCommentAndWhitespace(line);
+ if (name.length() != 0) {
+ result.add(service.cast(loader.loadClass(name).newInstance()));
+ }
+ }
+ } catch (Exception e) {
+ throw new MockitoConfigurationException(
+ "Failed to load " + service + " using " + resource, e);
+ } finally {
+ closeQuietly(in);
+ }
+ }
+ return result;
+ }
+
+ static List<String> readerToLines(Reader reader) throws IOException {
+ List<String> result = new ArrayList<String>();
+ BufferedReader lineReader = new BufferedReader(reader);
+ String line;
+ while ((line = lineReader.readLine()) != null) {
+ result.add(line);
+ }
+ return result;
+ }
+
+ static String stripCommentAndWhitespace(String line) {
+ int hash = line.indexOf('#');
+ if (hash != -1) {
+ line = line.substring(0, hash);
+ }
+ return line.trim();
+ }
+
+ private static void closeQuietly(InputStream in) {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/configuration/DefaultAnnotationEngine.java b/src/org/mockito/internal/configuration/DefaultAnnotationEngine.java
new file mode 100644
index 0000000..eaf1538
--- /dev/null
+++ b/src/org/mockito/internal/configuration/DefaultAnnotationEngine.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.configuration.AnnotationEngine;
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Initializes fields annotated with @{@link org.mockito.Mock} or @{@link org.mockito.Captor}.
+ *
+ * <p>
+ * The {@link #process(Class, Object)} method implementation <strong>does not</strong> process super classes!
+ *
+ * @see MockitoAnnotations
+ */
+@SuppressWarnings("unchecked")
+public class DefaultAnnotationEngine implements AnnotationEngine {
+ private final Map<Class<? extends Annotation>, FieldAnnotationProcessor<?>> annotationProcessorMap = new HashMap<Class<? extends Annotation>, FieldAnnotationProcessor<?>>();
+
+ public DefaultAnnotationEngine() {
+ registerAnnotationProcessor(Mock.class, new MockAnnotationProcessor());
+ registerAnnotationProcessor(MockitoAnnotations.Mock.class, new MockitoAnnotationsMockAnnotationProcessor());
+ registerAnnotationProcessor(Captor.class, new CaptorAnnotationProcessor());
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.AnnotationEngine#createMockFor(java.lang.annotation.Annotation, java.lang.reflect.Field)
+ */
+ @SuppressWarnings("deprecation")
+ public Object createMockFor(Annotation annotation, Field field) {
+ return forAnnotation(annotation).process(annotation, field);
+ }
+
+ private <A extends Annotation> FieldAnnotationProcessor<A> forAnnotation(A annotation) {
+ if (annotationProcessorMap.containsKey(annotation.annotationType())) {
+ return (FieldAnnotationProcessor<A>) annotationProcessorMap.get(annotation.annotationType());
+ }
+ return new FieldAnnotationProcessor<A>() {
+ public Object process(A annotation, Field field) {
+ return null;
+ }
+ };
+ }
+
+ private <A extends Annotation> void registerAnnotationProcessor(Class<A> annotationClass, FieldAnnotationProcessor<A> fieldAnnotationProcessor) {
+ annotationProcessorMap.put(annotationClass, fieldAnnotationProcessor);
+ }
+
+ public void process(Class<?> clazz, Object testInstance) {
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field field : fields) {
+ boolean alreadyAssigned = false;
+ for(Annotation annotation : field.getAnnotations()) {
+ Object mock = createMockFor(annotation, field);
+ if (mock != null) {
+ throwIfAlreadyAssigned(field, alreadyAssigned);
+ alreadyAssigned = true;
+ try {
+ new FieldSetter(testInstance, field).set(mock);
+ } catch (Exception e) {
+ throw new MockitoException("Problems setting field " + field.getName() + " annotated with "
+ + annotation, e);
+ }
+ }
+ }
+ }
+ }
+
+ void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) {
+ if (alreadyAssigned) {
+ new Reporter().moreThanOneAnnotationNotAllowed(field.getName());
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/configuration/DefaultInjectionEngine.java b/src/org/mockito/internal/configuration/DefaultInjectionEngine.java
new file mode 100644
index 0000000..ad4e879
--- /dev/null
+++ b/src/org/mockito/internal/configuration/DefaultInjectionEngine.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.internal.configuration.injection.MockInjection;
+
+import java.lang.reflect.Field;
+import java.util.Set;
+
+/**
+ * Inject mock/spies dependencies for fields annotated with @InjectMocks
+ * <p/>
+ * See {@link org.mockito.MockitoAnnotations}
+ */
+public class DefaultInjectionEngine {
+
+ public void injectMocksOnFields(Set<Field> needingInjection, Set<Object> mocks, Object testClassInstance) {
+ MockInjection.onFields(needingInjection, testClassInstance)
+ .withMocks(mocks)
+ .tryConstructorInjection()
+ .tryPropertyOrFieldInjection()
+ .handleSpyAnnotation()
+ .apply();
+ }
+
+}
diff --git a/src/org/mockito/internal/configuration/FieldAnnotationProcessor.java b/src/org/mockito/internal/configuration/FieldAnnotationProcessor.java
new file mode 100644
index 0000000..28f70b4
--- /dev/null
+++ b/src/org/mockito/internal/configuration/FieldAnnotationProcessor.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+/**
+ * Simple annotation processor interface.
+ */
+public interface FieldAnnotationProcessor<A extends Annotation> {
+ Object process(A annotation, Field field);
+}
diff --git a/src/org/mockito/internal/configuration/GlobalConfiguration.java b/src/org/mockito/internal/configuration/GlobalConfiguration.java
new file mode 100644
index 0000000..8adf6ba
--- /dev/null
+++ b/src/org/mockito/internal/configuration/GlobalConfiguration.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.ReturnValues;
+import org.mockito.configuration.AnnotationEngine;
+import org.mockito.configuration.DefaultMockitoConfiguration;
+import org.mockito.configuration.IMockitoConfiguration;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+
+/**
+ * Thread-safe wrapper on user-defined org.mockito.configuration.MockitoConfiguration implementation
+ */
+@SuppressWarnings("deprecation")//supressed until ReturnValues are removed
+public class GlobalConfiguration implements IMockitoConfiguration, Serializable {
+ static final long serialVersionUID = -2860353062105505938L;
+
+ private static ThreadLocal<IMockitoConfiguration> globalConfiguration = new ThreadLocal<IMockitoConfiguration>();
+
+ //back door for testing
+ IMockitoConfiguration getIt() {
+ return globalConfiguration.get();
+ }
+
+ public GlobalConfiguration() {
+ //Configuration should be loaded only once but I cannot really test it
+ if (globalConfiguration.get() == null) {
+ globalConfiguration.set(createConfig());
+ }
+ }
+
+ private IMockitoConfiguration createConfig() {
+ IMockitoConfiguration defaultConfiguration = new DefaultMockitoConfiguration();
+ IMockitoConfiguration config = new ClassPathLoader().loadConfiguration();
+ if (config != null) {
+ return config;
+ } else {
+ return defaultConfiguration;
+ }
+ }
+
+ public static void validate() {
+ new GlobalConfiguration();
+ }
+
+ public ReturnValues getReturnValues() {
+ return globalConfiguration.get().getReturnValues();
+ }
+
+ public AnnotationEngine getAnnotationEngine() {
+ return globalConfiguration.get().getAnnotationEngine();
+ }
+
+ public boolean cleansStackTrace() {
+ return globalConfiguration.get().cleansStackTrace();
+ }
+
+ public boolean enableClassCache() {
+ return globalConfiguration.get().enableClassCache();
+ }
+
+ public Answer<Object> getDefaultAnswer() {
+ return globalConfiguration.get().getDefaultAnswer();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/configuration/InjectingAnnotationEngine.java b/src/org/mockito/internal/configuration/InjectingAnnotationEngine.java
new file mode 100644
index 0000000..8a93fa2
--- /dev/null
+++ b/src/org/mockito/internal/configuration/InjectingAnnotationEngine.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.*;
+import org.mockito.configuration.AnnotationEngine;
+import org.mockito.internal.configuration.injection.scanner.InjectMocksScanner;
+import org.mockito.internal.configuration.injection.scanner.MockScanner;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
+
+/**
+ * See {@link MockitoAnnotations}
+ */
+@SuppressWarnings({"deprecation", "unchecked"})
+public class InjectingAnnotationEngine implements AnnotationEngine {
+ private AnnotationEngine delegate = new DefaultAnnotationEngine();
+ private AnnotationEngine spyAnnotationEngine = new SpyAnnotationEngine();
+
+ /***
+ * Create a mock using {@link DefaultAnnotationEngine}
+ *
+ * @see org.mockito.internal.configuration.DefaultAnnotationEngine
+ * @see org.mockito.configuration.AnnotationEngine#createMockFor(java.lang.annotation.Annotation, java.lang.reflect.Field)
+ */
+ @Deprecated
+ public Object createMockFor(Annotation annotation, Field field) {
+ return delegate.createMockFor(annotation, field);
+ }
+
+ /**
+ * Process the fields of the test instance and create Mocks, Spies, Captors and inject them on fields
+ * annotated @InjectMocks.
+ *
+ * <p>
+ * This code process the test class and the super classes.
+ * <ol>
+ * <li>First create Mocks, Spies, Captors.</li>
+ * <li>Then try to inject them.</li>
+ * </ol>
+ *
+ * @param clazz Not used
+ * @param testInstance The instance of the test, should not be null.
+ *
+ * @see org.mockito.configuration.AnnotationEngine#process(Class, Object)
+ */
+ public void process(Class<?> clazz, Object testInstance) {
+ processIndependentAnnotations(testInstance.getClass(), testInstance);
+ processInjectMocks(testInstance.getClass(), testInstance);
+ }
+
+ private void processInjectMocks(final Class<?> clazz, final Object testInstance) {
+ Class<?> classContext = clazz;
+ while (classContext != Object.class) {
+ injectMocks(testInstance);
+ classContext = classContext.getSuperclass();
+ }
+ }
+
+ private void processIndependentAnnotations(final Class<?> clazz, final Object testInstance) {
+ Class<?> classContext = clazz;
+ while (classContext != Object.class) {
+ //this will create @Mocks, @Captors, etc:
+ delegate.process(classContext, testInstance);
+ //this will create @Spies:
+ spyAnnotationEngine.process(classContext, testInstance);
+
+ classContext = classContext.getSuperclass();
+ }
+ }
+
+
+ /**
+ * Initializes mock/spies dependencies for objects annotated with
+ * @InjectMocks for given testClassInstance.
+ * <p>
+ * See examples in javadoc for {@link MockitoAnnotations} class.
+ *
+ * @param testClassInstance
+ * Test class, usually <code>this</code>
+ */
+ public void injectMocks(final Object testClassInstance) {
+ Class<?> clazz = testClassInstance.getClass();
+ Set<Field> mockDependentFields = new HashSet<Field>();
+ Set<Object> mocks = newMockSafeHashSet();
+
+ while (clazz != Object.class) {
+ new InjectMocksScanner(clazz).addTo(mockDependentFields);
+ new MockScanner(testClassInstance, clazz).addPreparedMocks(mocks);
+ clazz = clazz.getSuperclass();
+ }
+
+ new DefaultInjectionEngine().injectMocksOnFields(mockDependentFields, mocks, testClassInstance);
+ }
+
+}
diff --git a/src/org/mockito/internal/configuration/MockAnnotationProcessor.java b/src/org/mockito/internal/configuration/MockAnnotationProcessor.java
new file mode 100644
index 0000000..4d55074
--- /dev/null
+++ b/src/org/mockito/internal/configuration/MockAnnotationProcessor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.Mock;
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+
+import java.lang.reflect.Field;
+
+/**
+ * Instantiates a mock on a field annotated by {@link Mock}
+ */
+public class MockAnnotationProcessor implements FieldAnnotationProcessor<Mock> {
+ public Object process(Mock annotation, Field field) {
+ MockSettings mockSettings = Mockito.withSettings();
+ if (annotation.extraInterfaces().length > 0) { // never null
+ mockSettings.extraInterfaces(annotation.extraInterfaces());
+ }
+ if ("".equals(annotation.name())) {
+ mockSettings.name(field.getName());
+ } else {
+ mockSettings.name(annotation.name());
+ }
+ if(annotation.serializable()){
+ mockSettings.serializable();
+ }
+
+ // see @Mock answer default value
+ mockSettings.defaultAnswer(annotation.answer().get());
+ return Mockito.mock(field.getType(), mockSettings);
+ }
+}
diff --git a/src/org/mockito/internal/configuration/MockitoAnnotationsMockAnnotationProcessor.java b/src/org/mockito/internal/configuration/MockitoAnnotationsMockAnnotationProcessor.java
new file mode 100644
index 0000000..e8f7502
--- /dev/null
+++ b/src/org/mockito/internal/configuration/MockitoAnnotationsMockAnnotationProcessor.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations.Mock;
+
+import java.lang.reflect.Field;
+
+/**
+ * Instantiates a mock on a field annotated by {@link Mock}
+ */
+@SuppressWarnings("deprecation")
+public class MockitoAnnotationsMockAnnotationProcessor implements FieldAnnotationProcessor<Mock> {
+
+ public Object process(Mock annotation, Field field) {
+ return Mockito.mock(field.getType(), field.getName());
+ }
+}
diff --git a/src/org/mockito/internal/configuration/SpyAnnotationEngine.java b/src/org/mockito/internal/configuration/SpyAnnotationEngine.java
new file mode 100644
index 0000000..de1a195
--- /dev/null
+++ b/src/org/mockito/internal/configuration/SpyAnnotationEngine.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration;
+
+import org.mockito.*;
+import org.mockito.configuration.AnnotationEngine;
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.reflection.FieldInitializationReport;
+import org.mockito.internal.util.reflection.FieldInitializer;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+import static org.mockito.Mockito.withSettings;
+
+/**
+ * Process fields annotated with @Spy.
+ *
+ * <p>
+ * Will try transform the field in a spy as with <code>Mockito.spy()</code>.
+ * </p>
+ *
+ * <p>
+ * If the field is not initialized, will try to initialize it, with a no-arg constructor.
+ * </p>
+ *
+ * <p>
+ * If the field is also annotated with the <strong>compatible</strong> @InjectMocks then the field will be ignored,
+ * The injection engine will handle this specific case.
+ * </p>
+ *
+ * <p>This engine will fail, if the field is also annotated with incompatible Mockito annotations.
+ */
+@SuppressWarnings({"unchecked"})
+public class SpyAnnotationEngine implements AnnotationEngine {
+
+ public Object createMockFor(Annotation annotation, Field field) {
+ return null;
+ }
+
+ @SuppressWarnings("deprecation") // for MockitoAnnotations.Mock
+ public void process(Class<?> context, Object testInstance) {
+ Field[] fields = context.getDeclaredFields();
+ for (Field field : fields) {
+ if (field.isAnnotationPresent(Spy.class) && !field.isAnnotationPresent(InjectMocks.class)) {
+ assertNoIncompatibleAnnotations(Spy.class, field, Mock.class, org.mockito.MockitoAnnotations.Mock.class, Captor.class);
+ Object instance = null;
+ try {
+ FieldInitializationReport report = new FieldInitializer(testInstance, field).initialize();
+ instance = report.fieldInstance();
+ } catch (MockitoException e) {
+ new Reporter().cannotInitializeForSpyAnnotation(field.getName(), e);
+ }
+ try {
+ if (new MockUtil().isMock(instance)) {
+ // instance has been spied earlier
+ // for example happens when MockitoAnnotations.initMocks is called two times.
+ Mockito.reset(instance);
+ } else {
+ field.setAccessible(true);
+ field.set(testInstance, Mockito.mock(instance.getClass(), withSettings()
+ .spiedInstance(instance)
+ .defaultAnswer(Mockito.CALLS_REAL_METHODS)
+ .name(field.getName())));
+ }
+ } catch (IllegalAccessException e) {
+ throw new MockitoException("Problems initiating spied field " + field.getName(), e);
+ }
+ }
+ }
+ }
+
+ //TODO duplicated elsewhere
+ void assertNoIncompatibleAnnotations(Class annotation, Field field, Class... undesiredAnnotations) {
+ for (Class u : undesiredAnnotations) {
+ if (field.isAnnotationPresent(u)) {
+ new Reporter().unsupportedCombinationOfAnnotations(annotation.getSimpleName(), annotation.getClass().getSimpleName());
+ }
+ }
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/ConstructorInjection.java b/src/org/mockito/internal/configuration/injection/ConstructorInjection.java
new file mode 100644
index 0000000..10c01d1
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/ConstructorInjection.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.configuration.injection;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.reflection.FieldInitializationReport;
+import org.mockito.internal.util.reflection.FieldInitializer;
+import org.mockito.internal.util.reflection.FieldInitializer.ConstructorArgumentResolver;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Injection strategy based on constructor.
+ *
+ * <p>
+ * The strategy will search for the constructor with most parameters
+ * and try to resolve mocks by type.
+ * </p>
+ *
+ * <blockquote>
+ * TODO on missing mock type, shall it abandon or create "noname" mocks.
+ * TODO and what if the arg type is not mockable.
+ * </blockquote>
+ *
+ * <p>
+ * For now the algorithm tries to create anonymous mocks if an argument type is missing.
+ * If not possible the algorithm abandon resolution.
+ * </p>
+ */
+public class ConstructorInjection extends MockInjectionStrategy {
+
+ private ConstructorArgumentResolver argResolver;
+
+ public ConstructorInjection() { }
+
+ // visible for testing
+ ConstructorInjection(ConstructorArgumentResolver argResolver) {
+ this.argResolver = argResolver;
+ }
+
+ public boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates) {
+ try {
+ SimpleArgumentResolver simpleArgumentResolver = new SimpleArgumentResolver(mockCandidates);
+ FieldInitializationReport report = new FieldInitializer(fieldOwner, field, simpleArgumentResolver).initialize();
+
+ return report.fieldWasInitializedUsingContructorArgs();
+ } catch (MockitoException e) {
+ if(e.getCause() instanceof InvocationTargetException) {
+ Throwable realCause = e.getCause().getCause();
+ new Reporter().fieldInitialisationThrewException(field, realCause);
+ }
+ // other causes should be fine
+ return false;
+ }
+
+ }
+
+ /**
+ * Returns mocks that match the argument type, if not possible assigns null.
+ */
+ static class SimpleArgumentResolver implements ConstructorArgumentResolver {
+ final Set<Object> objects;
+
+ public SimpleArgumentResolver(Set<Object> objects) {
+ this.objects = objects;
+ }
+
+ public Object[] resolveTypeInstances(Class<?>... argTypes) {
+ List<Object> argumentInstances = new ArrayList<Object>(argTypes.length);
+ for (Class<?> argType : argTypes) {
+ argumentInstances.add(objectThatIsAssignableFrom(argType));
+ }
+ return argumentInstances.toArray();
+ }
+
+ private Object objectThatIsAssignableFrom(Class<?> argType) {
+ for (Object object : objects) {
+ if(argType.isAssignableFrom(object.getClass())) return object;
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/src/org/mockito/internal/configuration/injection/MockInjection.java b/src/org/mockito/internal/configuration/injection/MockInjection.java
new file mode 100644
index 0000000..3418bb6
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/MockInjection.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.configuration.injection;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.mockito.internal.util.Checks.checkItemsNotNull;
+import static org.mockito.internal.util.Checks.checkNotNull;
+import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
+
+/**
+ * Internal injection configuration utility.
+ *
+ * <p>
+ * Allow the user of this class to configure the way the injection of mocks will happen.
+ * </p>
+ *
+ */
+public class MockInjection {
+
+ /**
+ * Create a new configuration setup for a field
+ *
+ *
+ * @param field Field needing mock injection
+ * @param ofInstance Instance owning the <code>field</code>
+ * @return New configuration builder
+ */
+ public static OngoingMockInjection onField(Field field, Object ofInstance) {
+ return new OngoingMockInjection(field, ofInstance);
+ }
+
+ /**
+ * Create a new configuration setup for fields
+ *
+ *
+ * @param fields Fields needing mock injection
+ * @param ofInstance Instance owning the <code>field</code>
+ * @return New configuration builder
+ */
+ public static OngoingMockInjection onFields(Set<Field> fields, Object ofInstance) {
+ return new OngoingMockInjection(fields, ofInstance);
+ }
+
+ /**
+ * Ongoing configuration of the mock injector.
+ */
+ public static class OngoingMockInjection {
+ private Set<Field> fields = new HashSet<Field>();
+ private Set<Object> mocks = newMockSafeHashSet();
+ private Object fieldOwner;
+ private MockInjectionStrategy injectionStrategies = MockInjectionStrategy.nop();
+ private MockInjectionStrategy postInjectionStrategies = MockInjectionStrategy.nop();
+
+ private OngoingMockInjection(Field field, Object fieldOwner) {
+ this(Collections.singleton(field), fieldOwner);
+ }
+
+ private OngoingMockInjection(Set<Field> fields, Object fieldOwner) {
+ this.fieldOwner = checkNotNull(fieldOwner, "fieldOwner");
+ this.fields.addAll(checkItemsNotNull(fields, "fields"));
+ }
+
+ public OngoingMockInjection withMocks(Set<Object> mocks) {
+ this.mocks.addAll(checkNotNull(mocks, "mocks"));
+ return this;
+ }
+
+ public OngoingMockInjection tryConstructorInjection() {
+ injectionStrategies.thenTry(new ConstructorInjection());
+ return this;
+ }
+
+ public OngoingMockInjection tryPropertyOrFieldInjection() {
+ injectionStrategies.thenTry(new PropertyAndSetterInjection());
+ return this;
+ }
+
+ public OngoingMockInjection handleSpyAnnotation() {
+ postInjectionStrategies.thenTry(new SpyOnInjectedFieldsHandler());
+ return this;
+ }
+
+ public void apply() {
+ for (Field field : fields) {
+ injectionStrategies.process(field, fieldOwner, mocks);
+ postInjectionStrategies.process(field, fieldOwner, mocks);
+ }
+ }
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/MockInjectionStrategy.java b/src/org/mockito/internal/configuration/injection/MockInjectionStrategy.java
new file mode 100644
index 0000000..b5b762e
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/MockInjectionStrategy.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.configuration.injection;
+
+import java.lang.reflect.Field;
+import java.util.Set;
+
+/**
+ * Injector strategy contract
+ */
+public abstract class MockInjectionStrategy {
+
+ /**
+ * NOP Strategy that will always try the next strategy.
+ */
+ public static final MockInjectionStrategy nop() {
+ return new MockInjectionStrategy() {
+ protected boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates) {
+ return false;
+ }
+ };
+ }
+
+
+ private MockInjectionStrategy nextStrategy;
+
+ /**
+ * Enqueue next injection strategy.
+ *
+ * <p>
+ * The implementation should take care of the actual calling if required.
+ * </p>
+ *
+ * @param strategy Queued strategy.
+ * @return The passed strategy instance to allow chaining.
+ */
+ public MockInjectionStrategy thenTry(MockInjectionStrategy strategy) {
+ if(nextStrategy != null) {
+ nextStrategy.thenTry(strategy);
+ } else {
+ nextStrategy = strategy;
+ }
+ return strategy;
+ }
+
+ /**
+ * Actually inject mockCandidates on field.
+ *
+ * <p>
+ * Actual algorithm is defined in the implementations of {@link #processInjection(Field, Object, Set)}.
+ * However if injection occurred successfully, the process should return <code>true</code>,
+ * and <code>false</code> otherwise.
+ * </p>
+ *
+ * <p>
+ * The code takes care of calling the next strategy if available and if of course if required
+ * </p>
+ *
+ * @param onField Field needing injection.
+ * @param fieldOwnedBy The owning instance of the field.
+ * @param mockCandidates A set of mock candidate, that might be injected.
+ * @return <code>true</code> if successful, <code>false</code> otherwise.
+ */
+ public boolean process(Field onField, Object fieldOwnedBy, Set<Object> mockCandidates) {
+ if(processInjection(onField, fieldOwnedBy, mockCandidates)) {
+ return true;
+ }
+ return relayProcessToNextStrategy(onField, fieldOwnedBy, mockCandidates);
+ }
+
+ /**
+ * Process actual injection.
+ *
+ * <p>
+ * Don't call this method directly, instead call {@link #process(Field, Object, Set)}
+ * </p>
+ *
+ * @param field Field needing injection
+ * @param fieldOwner Field owner instance.
+ * @param mockCandidates Pool of mocks to inject.
+ * @return <code>true</code> if injection occurred, <code>false</code> otherwise
+ */
+ protected abstract boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates);
+
+ private boolean relayProcessToNextStrategy(Field field, Object fieldOwner, Set<Object> mockCandidates) {
+ return nextStrategy != null && nextStrategy.process(field, fieldOwner, mockCandidates);
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java b/src/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java
new file mode 100644
index 0000000..2f6ecc6
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.configuration.injection;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.configuration.injection.filter.FinalMockCandidateFilter;
+import org.mockito.internal.configuration.injection.filter.MockCandidateFilter;
+import org.mockito.internal.configuration.injection.filter.NameBasedCandidateFilter;
+import org.mockito.internal.configuration.injection.filter.TypeBasedCandidateFilter;
+import org.mockito.internal.util.collections.ListUtil;
+import org.mockito.internal.util.reflection.FieldInitializationReport;
+import org.mockito.internal.util.reflection.FieldInitializer;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
+
+/**
+ * Inject mocks using first setters then fields, if no setters available.
+ *
+ * <p>
+ * <u>Algorithm :<br></u>
+ * for each field annotated by @InjectMocks
+ * <ul>
+ * <li>initialize field annotated by @InjectMocks
+ * <li>for each fields of a class in @InjectMocks type hierarchy
+ * <ul>
+ * <li>make a copy of mock candidates
+ * <li>order fields rom sub-type to super-type, then by field name
+ * <li>for the list of fields in a class try two passes of :
+ * <ul>
+ * <li>find mock candidate by type
+ * <li>if more than <b>*one*</b> candidate find mock candidate on name
+ * <li>if one mock candidate then
+ * <ul>
+ * <li>set mock by property setter if possible
+ * <li>else set mock by field injection
+ * </ul>
+ * <li>remove mock from mocks copy (mocks are just injected once in a class)
+ * <li>remove injected field from list of class fields
+ * </ul>
+ * <li>else don't fail, user will then provide dependencies
+ * </ul>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * <u>Note:</u> If the field needing injection is not initialized, the strategy tries
+ * to create one using a no-arg constructor of the field type.
+ * </p>
+ */
+public class PropertyAndSetterInjection extends MockInjectionStrategy {
+
+ private final MockCandidateFilter mockCandidateFilter = new TypeBasedCandidateFilter(new NameBasedCandidateFilter(new FinalMockCandidateFilter()));
+ private Comparator<Field> superTypesLast = new FieldTypeAndNameComparator();
+
+ private ListUtil.Filter<Field> notFinalOrStatic = new ListUtil.Filter<Field>() {
+ public boolean isOut(Field object) {
+ return Modifier.isFinal(object.getModifiers()) || Modifier.isStatic(object.getModifiers());
+ }
+ };
+
+
+ public boolean processInjection(Field injectMocksField, Object injectMocksFieldOwner, Set<Object> mockCandidates) {
+ // Set<Object> mocksToBeInjected = new HashSet<Object>(mockCandidates);
+ FieldInitializationReport report = initializeInjectMocksField(injectMocksField, injectMocksFieldOwner);
+
+ // for each field in the class hierarchy
+ boolean injectionOccurred = false;
+ Class<?> fieldClass = report.fieldClass();
+ Object fieldInstanceNeedingInjection = report.fieldInstance();
+ while (fieldClass != Object.class) {
+ injectionOccurred |= injectMockCandidates(fieldClass, newMockSafeHashSet(mockCandidates), fieldInstanceNeedingInjection);
+ fieldClass = fieldClass.getSuperclass();
+ }
+ return injectionOccurred;
+ }
+
+ private FieldInitializationReport initializeInjectMocksField(Field field, Object fieldOwner) {
+ FieldInitializationReport report = null;
+ try {
+ report = new FieldInitializer(fieldOwner, field).initialize();
+ } catch (MockitoException e) {
+ if(e.getCause() instanceof InvocationTargetException) {
+ Throwable realCause = e.getCause().getCause();
+ new Reporter().fieldInitialisationThrewException(field, realCause);
+ }
+ new Reporter().cannotInitializeForInjectMocksAnnotation(field.getName(), e);
+ }
+ return report; // never null
+ }
+
+
+ private boolean injectMockCandidates(Class<?> awaitingInjectionClazz, Set<Object> mocks, Object instance) {
+ boolean injectionOccurred = false;
+ List<Field> orderedInstanceFields = orderedInstanceFieldsFrom(awaitingInjectionClazz);
+ // pass 1
+ injectionOccurred |= injectMockCandidatesOnFields(mocks, instance, injectionOccurred, orderedInstanceFields);
+ // pass 2
+ injectionOccurred |= injectMockCandidatesOnFields(mocks, instance, injectionOccurred, orderedInstanceFields);
+ return injectionOccurred;
+ }
+
+ private boolean injectMockCandidatesOnFields(Set<Object> mocks, Object instance, boolean injectionOccurred, List<Field> orderedInstanceFields) {
+ for (Iterator<Field> it = orderedInstanceFields.iterator(); it.hasNext(); ) {
+ Field field = it.next();
+ Object injected = mockCandidateFilter.filterCandidate(mocks, field, instance).thenInject();
+ if (injected != null) {
+ injectionOccurred |= true;
+ mocks.remove(injected);
+ it.remove();
+ }
+ }
+ return injectionOccurred;
+ }
+
+ private List<Field> orderedInstanceFieldsFrom(Class<?> awaitingInjectionClazz) {
+ List<Field> declaredFields = Arrays.asList(awaitingInjectionClazz.getDeclaredFields());
+ declaredFields = ListUtil.filter(declaredFields, notFinalOrStatic);
+
+ Collections.sort(declaredFields, superTypesLast);
+
+ return declaredFields;
+ }
+
+ static class FieldTypeAndNameComparator implements Comparator<Field> {
+ public int compare(Field field1, Field field2) {
+ Class<?> field1Type = field1.getType();
+ Class<?> field2Type = field2.getType();
+
+ // if same type, compares on field name
+ if (field1Type == field2Type) {
+ return field1.getName().compareTo(field2.getName());
+ }
+ if(field1Type.isAssignableFrom(field2Type)) {
+ return 1;
+ }
+ if(field2Type.isAssignableFrom(field1Type)) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java b/src/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java
new file mode 100644
index 0000000..963bf27
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.configuration.injection;
+
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.reflection.FieldReader;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.lang.reflect.Field;
+import java.util.Set;
+
+import static org.mockito.Mockito.withSettings;
+
+/**
+ * Handler for field annotated with @InjectMocks and @Spy.
+ *
+ * <p>
+ * The handler assumes that field initialization AND injection already happened.
+ * So if the field is still null, then nothing will happen there.
+ * </p>
+ */
+public class SpyOnInjectedFieldsHandler extends MockInjectionStrategy {
+
+ @Override
+ protected boolean processInjection(Field field, Object fieldOwner, Set<Object> mockCandidates) {
+ FieldReader fieldReader = new FieldReader(fieldOwner, field);
+
+ // TODO refoctor : code duplicated in SpyAnnotationEngine
+ if(!fieldReader.isNull() && field.isAnnotationPresent(Spy.class)) {
+ try {
+ Object instance = fieldReader.read();
+ if (new MockUtil().isMock(instance)) {
+ // A. instance has been spied earlier
+ // B. protect against multiple use of MockitoAnnotations.initMocks()
+ Mockito.reset(instance);
+ } else {
+ new FieldSetter(fieldOwner, field).set(
+ Mockito.mock(instance.getClass(), withSettings()
+ .spiedInstance(instance)
+ .defaultAnswer(Mockito.CALLS_REAL_METHODS)
+ .name(field.getName()))
+ );
+ }
+ } catch (Exception e) {
+ throw new MockitoException("Problems initiating spied field " + field.getName(), e);
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java b/src/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java
new file mode 100644
index 0000000..894b113
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/filter/FinalMockCandidateFilter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.filter;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.util.reflection.BeanPropertySetter;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+
+/**
+ * This node returns an actual injecter which will be either :
+ *
+ * <ul>
+ * <li>an {@link OngoingInjecter} that do nothing if a candidate couldn't be found</li>
+ * <li>an {@link OngoingInjecter} that will try to inject the candidate trying first the property setter then if not possible try the field access</li>
+ * </ul>
+ */
+public class FinalMockCandidateFilter implements MockCandidateFilter {
+ public OngoingInjecter filterCandidate(final Collection<Object> mocks, final Field field, final Object fieldInstance) {
+ if(mocks.size() == 1) {
+ final Object matchingMock = mocks.iterator().next();
+
+ return new OngoingInjecter() {
+ public Object thenInject() {
+ try {
+ if (!new BeanPropertySetter(fieldInstance, field).set(matchingMock)) {
+ new FieldSetter(fieldInstance, field).set(matchingMock);
+ }
+ } catch (RuntimeException e) {
+ new Reporter().cannotInjectDependency(field, matchingMock, e);
+ }
+ return matchingMock;
+ }
+ };
+ }
+
+ return new OngoingInjecter() {
+ public Object thenInject() {
+ return null;
+ }
+ };
+
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java b/src/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java
new file mode 100644
index 0000000..f407f82
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.filter;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+
+public interface MockCandidateFilter {
+
+ OngoingInjecter filterCandidate(
+ Collection<Object> mocks,
+ Field fieldToBeInjected,
+ Object fieldInstance
+ );
+
+}
diff --git a/src/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java b/src/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java
new file mode 100644
index 0000000..a5c127d
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.filter;
+
+import org.mockito.internal.util.MockUtil;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class NameBasedCandidateFilter implements MockCandidateFilter {
+ private final MockCandidateFilter next;
+ private final MockUtil mockUtil = new MockUtil();
+
+ public NameBasedCandidateFilter(MockCandidateFilter next) {
+ this.next = next;
+ }
+
+ public OngoingInjecter filterCandidate(Collection<Object> mocks, Field field, Object fieldInstance) {
+ List<Object> mockNameMatches = new ArrayList<Object>();
+ if(mocks.size() > 1) {
+ for (Object mock : mocks) {
+ if (field.getName().equals(mockUtil.getMockName(mock).toString())) {
+ mockNameMatches.add(mock);
+ }
+ }
+ return next.filterCandidate(mockNameMatches, field, fieldInstance);
+ }
+ return next.filterCandidate(mocks, field, fieldInstance);
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/filter/OngoingInjecter.java b/src/org/mockito/internal/configuration/injection/filter/OngoingInjecter.java
new file mode 100644
index 0000000..ee905fa
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/filter/OngoingInjecter.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.filter;
+
+/**
+ * Allow the ongoing injection of a mock candidate.
+ */
+public interface OngoingInjecter {
+
+ /**
+ * Inject the mock.
+ *
+ * <p>
+ * Please check the actual implementation.
+ * </p>
+ *
+ * @return the mock that was injected, <code>null</code> otherwise.
+ */
+ Object thenInject();
+
+}
diff --git a/src/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java b/src/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java
new file mode 100644
index 0000000..46067ef
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.filter;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class TypeBasedCandidateFilter implements MockCandidateFilter {
+
+ MockCandidateFilter next;
+
+ public TypeBasedCandidateFilter(MockCandidateFilter next) {
+ this.next = next;
+ }
+
+ public OngoingInjecter filterCandidate(Collection<Object> mocks, Field field, Object fieldInstance) {
+ List<Object> mockTypeMatches = new ArrayList<Object>();
+ for (Object mock : mocks) {
+ if (field.getType().isAssignableFrom(mock.getClass())) {
+ mockTypeMatches.add(mock);
+ }
+ }
+
+ return next.filterCandidate(mockTypeMatches, field, fieldInstance);
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java b/src/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java
new file mode 100644
index 0000000..a225b33
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.scanner;
+
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.exceptions.Reporter;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Scan field for injection.
+ */
+@SuppressWarnings("deprecation")
+public class InjectMocksScanner {
+ private final Class<?> clazz;
+
+ /**
+ * Create a new InjectMocksScanner for the given clazz on the given instance
+ *
+ * @param clazz Current class in the hierarchy of the test
+ */
+ public InjectMocksScanner(Class<?> clazz) {
+ this.clazz = clazz;
+ }
+
+
+ /**
+ * Add the fields annotated by @{@link InjectMocks}
+ *
+ * @param mockDependentFields Set of fields annotated by @{@link InjectMocks}
+ */
+ public void addTo(Set<Field> mockDependentFields) {
+ mockDependentFields.addAll(scan());
+ }
+
+ /**
+ * Scan fields annotated by @InjectMocks
+ *
+ * @return Fields that depends on Mock
+ */
+ private Set<Field> scan() {
+ Set<Field> mockDependentFields = new HashSet<Field>();
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field field : fields) {
+ if (null != field.getAnnotation(InjectMocks.class)) {
+ assertNoAnnotations(field, Mock.class, MockitoAnnotations.Mock.class, Captor.class);
+ mockDependentFields.add(field);
+ }
+ }
+
+ return mockDependentFields;
+ }
+
+ void assertNoAnnotations(final Field field, final Class... annotations) {
+ for (Class annotation : annotations) {
+ if (field.isAnnotationPresent(annotation)) {
+ new Reporter().unsupportedCombinationOfAnnotations(annotation.getSimpleName(), InjectMocks.class.getSimpleName());
+ }
+ }
+ }
+}
diff --git a/src/org/mockito/internal/configuration/injection/scanner/MockScanner.java b/src/org/mockito/internal/configuration/injection/scanner/MockScanner.java
new file mode 100644
index 0000000..e013627
--- /dev/null
+++ b/src/org/mockito/internal/configuration/injection/scanner/MockScanner.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.configuration.injection.scanner;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.reflection.FieldReader;
+
+import java.lang.reflect.Field;
+import java.util.Set;
+
+import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
+
+/**
+ * Scan mocks, and prepare them if needed.
+ */
+public class MockScanner {
+ private MockUtil mockUtil = new MockUtil();
+ private final Object instance;
+ private final Class<?> clazz;
+
+ /**
+ * Creates a MockScanner.
+ *
+ * @param instance The test instance
+ * @param clazz The class in the type hierarchy of this instance.
+ */
+ public MockScanner(Object instance, Class<?> clazz) {
+ this.instance = instance;
+ this.clazz = clazz;
+ }
+
+ /**
+ * Add the scanned and prepared mock instance to the given collection.
+ *
+ * <p>
+ * The preparation of mocks consists only in defining a MockName if not already set.
+ * </p>
+ *
+ * @param mocks Set of mocks
+ */
+ public void addPreparedMocks(Set<Object> mocks) {
+ mocks.addAll(scan());
+ }
+
+ /**
+ * Scan and prepare mocks for the given <code>testClassInstance</code> and <code>clazz</code> in the type hierarchy.
+ *
+ * @return A prepared set of mock
+ */
+ private Set<Object> scan() {
+ Set<Object> mocks = newMockSafeHashSet();
+ for (Field field : clazz.getDeclaredFields()) {
+ // mock or spies only
+ FieldReader fieldReader = new FieldReader(instance, field);
+
+ Object mockInstance = preparedMock(fieldReader.read(), field);
+ if (mockInstance != null) {
+ mocks.add(mockInstance);
+ }
+ }
+ return mocks;
+ }
+
+ private Object preparedMock(Object instance, Field field) {
+ if (isAnnotatedByMockOrSpy(field)) {
+ return instance;
+ } else if (isMockOrSpy(instance)) {
+ mockUtil.maybeRedefineMockName(instance, field.getName());
+ return instance;
+ }
+ return null;
+ }
+
+ private boolean isAnnotatedByMockOrSpy(Field field) {
+ return null != field.getAnnotation(Spy.class)
+ || null != field.getAnnotation(Mock.class)
+ || null != field.getAnnotation(MockitoAnnotations.Mock.class);
+ }
+
+ private boolean isMockOrSpy(Object instance) {
+ return mockUtil.isMock(instance)
+ || mockUtil.isSpy(instance);
+ }
+}
diff --git a/src/org/mockito/internal/configuration/package.html b/src/org/mockito/internal/configuration/package.html
new file mode 100644
index 0000000..5d4669a
--- /dev/null
+++ b/src/org/mockito/internal/configuration/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Mockito configuration
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/creation/DelegatingMethod.java b/src/org/mockito/internal/creation/DelegatingMethod.java
new file mode 100644
index 0000000..e6176f5
--- /dev/null
+++ b/src/org/mockito/internal/creation/DelegatingMethod.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation;
+
+import java.lang.reflect.Method;
+
+import org.mockito.internal.invocation.MockitoMethod;
+
+public class DelegatingMethod implements MockitoMethod {
+
+ private final Method method;
+
+ public DelegatingMethod(Method method) {
+ assert method != null : "Method cannot be null";
+ this.method = method;
+ }
+
+ public Class<?>[] getExceptionTypes() {
+ return method.getExceptionTypes();
+ }
+
+ public Method getJavaMethod() {
+ return method;
+ }
+
+ public String getName() {
+ return method.getName();
+ }
+
+ public Class<?>[] getParameterTypes() {
+ return method.getParameterTypes();
+ }
+
+ public Class<?> getReturnType() {
+ return method.getReturnType();
+ }
+
+ public boolean isVarArgs() {
+ return method.isVarArgs();
+ }
+
+ @Override
+ public int hashCode() {
+ return 1;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return method.equals(obj);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/creation/MockSettingsImpl.java b/src/org/mockito/internal/creation/MockSettingsImpl.java
new file mode 100644
index 0000000..d226403
--- /dev/null
+++ b/src/org/mockito/internal/creation/MockSettingsImpl.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation;
+
+import org.mockito.MockSettings;
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.debugging.VerboseMockInvocationLogger;
+import org.mockito.internal.util.MockCreationValidator;
+import org.mockito.internal.util.MockNameImpl;
+import org.mockito.internal.util.MockitoMock;
+import org.mockito.internal.util.MockitoSpy;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.MockName;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.mockito.internal.util.collections.Sets.newSet;
+
+@SuppressWarnings("unchecked")
+public class MockSettingsImpl<T> extends CreationSettings<T> implements MockSettings, MockCreationSettings<T> {
+
+ private static final long serialVersionUID = 4475297236197939569L;
+
+ public MockSettings serializable() {
+ this.serializable = true;
+ return this;
+ }
+
+ public MockSettings extraInterfaces(Class... extraInterfaces) {
+ if (extraInterfaces == null || extraInterfaces.length == 0) {
+ new Reporter().extraInterfacesRequiresAtLeastOneInterface();
+ }
+
+ for (Class i : extraInterfaces) {
+ if (i == null) {
+ new Reporter().extraInterfacesDoesNotAcceptNullParameters();
+ } else if (!i.isInterface()) {
+ new Reporter().extraInterfacesAcceptsOnlyInterfaces(i);
+ }
+ }
+ this.extraInterfaces = newSet(extraInterfaces);
+ return this;
+ }
+
+ public MockName getMockName() {
+ return mockName;
+ }
+
+ public Set<Class> getExtraInterfaces() {
+ return extraInterfaces;
+ }
+
+ public Object getSpiedInstance() {
+ return spiedInstance;
+ }
+
+ public MockSettings name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public MockSettings spiedInstance(Object spiedInstance) {
+ this.spiedInstance = spiedInstance;
+ return this;
+ }
+
+ public MockSettings defaultAnswer(Answer defaultAnswer) {
+ this.defaultAnswer = defaultAnswer;
+ if (defaultAnswer == null) {
+ new Reporter().defaultAnswerDoesNotAcceptNullParameter();
+ }
+ return this;
+ }
+
+ public Answer<Object> getDefaultAnswer() {
+ return defaultAnswer;
+ }
+
+ public boolean isSerializable() {
+ return serializable;
+ }
+
+ public MockSettingsImpl stubOnly() {
+ this.stubOnly = true;
+ return this;
+ }
+
+ public boolean isStubOnly() {
+ return this.stubOnly;
+ }
+
+ public MockSettings verboseLogging() {
+ if (!invocationListenersContainsType(VerboseMockInvocationLogger.class)) {
+ invocationListeners(new VerboseMockInvocationLogger());
+ }
+ return this;
+ }
+
+ public MockSettings invocationListeners(InvocationListener... listeners) {
+ if (listeners == null || listeners.length == 0) {
+ new Reporter().invocationListenersRequiresAtLeastOneListener();
+ }
+ for (InvocationListener listener : listeners) {
+ if (listener == null) {
+ new Reporter().invocationListenerDoesNotAcceptNullParameters();
+ }
+ this.invocationListeners.add(listener);
+ }
+ return this;
+ }
+
+ private boolean invocationListenersContainsType(Class<?> clazz) {
+ for (InvocationListener listener : invocationListeners) {
+ if (listener.getClass().equals(clazz)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public List<InvocationListener> getInvocationListeners() {
+ return this.invocationListeners;
+ }
+
+ public boolean hasInvocationListeners() {
+ return !invocationListeners.isEmpty();
+ }
+
+ public Class<T> getTypeToMock() {
+ return typeToMock;
+ }
+
+ public MockCreationSettings<T> confirm(Class<T> typeToMock) {
+ return validatedSettings(typeToMock, this);
+ }
+
+ private static <T> CreationSettings<T> validatedSettings(Class<T> typeToMock, CreationSettings<T> source) {
+ MockCreationValidator validator = new MockCreationValidator();
+
+ validator.validateType(typeToMock);
+ validator.validateExtraInterfaces(typeToMock, source.getExtraInterfaces());
+ validator.validateMockedType(typeToMock, source.getSpiedInstance());
+
+ //TODO SF - add this validation and also add missing coverage
+// validator.validateDelegatedInstance(classToMock, settings.getDelegatedInstance());
+
+ validator.validateSerializable(typeToMock, source.isSerializable());
+
+ CreationSettings<T> settings = new CreationSettings<T>(source);
+ settings.setMockName(new MockNameImpl(source.getName(), typeToMock));
+ settings.setTypeToMock(typeToMock);
+ settings.setExtraInterfaces(prepareExtraInterfaces(source));
+ return settings;
+ }
+
+ private static Set<Class> prepareExtraInterfaces(CreationSettings settings) {
+ Set<Class> interfaces = new HashSet<Class>(settings.getExtraInterfaces());
+ interfaces.add(MockitoMock.class);
+ if(settings.isSerializable()) {
+ interfaces.add(Serializable.class);
+ }
+ if (settings.getSpiedInstance() != null) {
+ interfaces.add(MockitoSpy.class);
+ }
+ return interfaces;
+ }
+
+}
+
diff --git a/src/org/mockito/internal/creation/package.html b/src/org/mockito/internal/creation/package.html
new file mode 100644
index 0000000..533a36a
--- /dev/null
+++ b/src/org/mockito/internal/creation/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Mock object creation.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/creation/settings/CreationSettings.java b/src/org/mockito/internal/creation/settings/CreationSettings.java
new file mode 100644
index 0000000..94d8dc6
--- /dev/null
+++ b/src/org/mockito/internal/creation/settings/CreationSettings.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.creation.settings;
+
+import org.mockito.listeners.InvocationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.MockName;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * by Szczepan Faber, created at: 4/9/12
+ */
+public class CreationSettings<T> implements MockCreationSettings<T>, Serializable {
+ private static final long serialVersionUID = -6789800638070123629L;
+
+ protected Class<T> typeToMock;
+ protected Set<Class> extraInterfaces = new LinkedHashSet<Class>();
+ protected String name;
+ protected Object spiedInstance;
+ protected Answer<Object> defaultAnswer;
+ protected MockName mockName;
+ protected boolean serializable;
+ protected List<InvocationListener> invocationListeners = new ArrayList<InvocationListener>();
+ protected boolean stubOnly;
+
+ public CreationSettings() {}
+
+ @SuppressWarnings("unchecked")
+ public CreationSettings(CreationSettings copy) {
+ this.typeToMock = copy.typeToMock;
+ this.extraInterfaces = copy.extraInterfaces;
+ this.name = copy.name;
+ this.spiedInstance = copy.spiedInstance;
+ this.defaultAnswer = copy.defaultAnswer;
+ this.mockName = copy.mockName;
+ this.serializable = copy.serializable;
+ this.invocationListeners = copy.invocationListeners;
+ this.stubOnly = copy.stubOnly;
+ }
+
+ public Class<T> getTypeToMock() {
+ return typeToMock;
+ }
+
+ public CreationSettings<T> setTypeToMock(Class<T> typeToMock) {
+ this.typeToMock = typeToMock;
+ return this;
+ }
+
+ public Set<Class> getExtraInterfaces() {
+ return extraInterfaces;
+ }
+
+ public CreationSettings<T> setExtraInterfaces(Set<Class> extraInterfaces) {
+ this.extraInterfaces = extraInterfaces;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Object getSpiedInstance() {
+ return spiedInstance;
+ }
+
+ public Answer<Object> getDefaultAnswer() {
+ return defaultAnswer;
+ }
+
+ public MockName getMockName() {
+ return mockName;
+ }
+
+ public CreationSettings<T> setMockName(MockName mockName) {
+ this.mockName = mockName;
+ return this;
+ }
+
+ public boolean isSerializable() {
+ return serializable;
+ }
+
+ public List<InvocationListener> getInvocationListeners() {
+ return invocationListeners;
+ }
+
+ public boolean isStubOnly() {
+ return stubOnly;
+ }
+
+}
diff --git a/src/org/mockito/internal/debugging/FindingsListener.java b/src/org/mockito/internal/debugging/FindingsListener.java
new file mode 100644
index 0000000..e579cbf
--- /dev/null
+++ b/src/org/mockito/internal/debugging/FindingsListener.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+public interface FindingsListener {
+ void foundStubCalledWithDifferentArgs(Invocation unused, InvocationMatcher unstubbed);
+
+ void foundUnusedStub(Invocation unused);
+
+ void foundUnstubbed(InvocationMatcher unstubbed);
+}
diff --git a/src/org/mockito/internal/debugging/Localized.java b/src/org/mockito/internal/debugging/Localized.java
new file mode 100644
index 0000000..619e466
--- /dev/null
+++ b/src/org/mockito/internal/debugging/Localized.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+
+import org.mockito.invocation.Location;
+
+public class Localized<T> {
+
+ private final T object;
+ private final Location location;
+
+ public Localized(T object) {
+ this.object = object;
+ location = new LocationImpl();
+ }
+
+ public T getObject() {
+ return object;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/debugging/LocationImpl.java b/src/org/mockito/internal/debugging/LocationImpl.java
new file mode 100644
index 0000000..d04c513
--- /dev/null
+++ b/src/org/mockito/internal/debugging/LocationImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.internal.exceptions.stacktrace.StackTraceFilter;
+import org.mockito.invocation.Location;
+
+import java.io.Serializable;
+
+public class LocationImpl implements Location, Serializable {
+
+ private static final long serialVersionUID = -9054861157390980624L;
+ private final Throwable stackTraceHolder;
+ private final StackTraceFilter stackTraceFilter;
+
+ public LocationImpl() {
+ this(new StackTraceFilter());
+ }
+
+ public LocationImpl(StackTraceFilter stackTraceFilter) {
+ this.stackTraceFilter = stackTraceFilter;
+ stackTraceHolder = new Throwable();
+ }
+
+ @Override
+ public String toString() {
+ StackTraceElement[] filtered = stackTraceFilter.filter(stackTraceHolder.getStackTrace(), false);
+ if (filtered.length == 0) {
+ return "-> at <<unknown line>>";
+ }
+ return "-> at " + filtered[0].toString();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/debugging/LoggingListener.java b/src/org/mockito/internal/debugging/LoggingListener.java
new file mode 100644
index 0000000..99f6638
--- /dev/null
+++ b/src/org/mockito/internal/debugging/LoggingListener.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.invocation.Invocation;
+
+import static org.mockito.internal.util.StringJoiner.join;
+
+public class LoggingListener implements FindingsListener {
+ private boolean warnAboutUnstubbed;
+ private final MockitoLogger logger;
+
+ public LoggingListener(boolean warnAboutUnstubbed, MockitoLogger logger) {
+ this.warnAboutUnstubbed = warnAboutUnstubbed;
+ this.logger = logger;
+ }
+
+ public void foundStubCalledWithDifferentArgs(Invocation unused, InvocationMatcher unstubbed) {
+ logger.log(join(
+ " *** Stubbing warnings from Mockito: *** ",
+ "",
+ "stubbed with those args here " + unused.getLocation(),
+ "BUT called with different args " + unstubbed.getInvocation().getLocation(),
+ ""));
+ }
+
+ public void foundUnusedStub(Invocation unused) {
+ logger.log("This stubbing was never used " + unused.getLocation() + "\n");
+ }
+
+ public void foundUnstubbed(InvocationMatcher unstubbed) {
+ if (warnAboutUnstubbed) {
+ logger.log(join(
+ "This method was not stubbed ",
+ unstubbed,
+ unstubbed.getInvocation().getLocation(),
+ ""));
+ }
+ }
+
+ public boolean isWarnAboutUnstubbed() {
+ return warnAboutUnstubbed;
+ }
+
+ public MockitoLogger getLogger() {
+ return logger;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/debugging/MockitoDebuggerImpl.java b/src/org/mockito/internal/debugging/MockitoDebuggerImpl.java
new file mode 100644
index 0000000..06dcf56
--- /dev/null
+++ b/src/org/mockito/internal/debugging/MockitoDebuggerImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.MockitoDebugger;
+import org.mockito.internal.invocation.UnusedStubsFinder;
+import org.mockito.internal.invocation.finder.AllInvocationsFinder;
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+import static java.util.Arrays.asList;
+
+public class MockitoDebuggerImpl implements MockitoDebugger {
+
+ private AllInvocationsFinder allInvocationsFinder = new AllInvocationsFinder();
+ private UnusedStubsFinder unusedStubsFinder = new UnusedStubsFinder();
+
+ public String printInvocations(Object ... mocks) {
+ String out = "";
+ List<Invocation> invocations = allInvocationsFinder.find(asList(mocks));
+ out += line("********************************");
+ out += line("*** Mockito interactions log ***");
+ out += line("********************************");
+ for(Invocation i:invocations) {
+ out += line(i.toString());
+ out += line(" invoked: " + i.getLocation());
+ if (i.stubInfo() != null) {
+ out += line(" stubbed: " + i.stubInfo().stubbedAt().toString());
+ }
+ }
+
+ invocations = unusedStubsFinder.find(asList(mocks));
+ if (invocations.isEmpty()) {
+ return print(out);
+ }
+ out += line("********************************");
+ out += line("*** Unused stubs ***");
+ out += line("********************************");
+
+ for(Invocation i:invocations) {
+ out += line(i.toString());
+ out += line(" stubbed: " + i.getLocation());
+ }
+ return print(out);
+ }
+
+ private String line(String text) {
+ return text + "\n";
+ }
+
+ private String print(String out) {
+ System.out.println(out);
+ return out;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/debugging/VerboseMockInvocationLogger.java b/src/org/mockito/internal/debugging/VerboseMockInvocationLogger.java
new file mode 100644
index 0000000..2a81074
--- /dev/null
+++ b/src/org/mockito/internal/debugging/VerboseMockInvocationLogger.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.debugging;
+
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.listeners.MethodInvocationReport;
+
+import java.io.PrintStream;
+
+/**
+ * Logs all invocations to standard output.
+ *
+ * Used for debugging interactions with a mock.
+ */
+public class VerboseMockInvocationLogger implements InvocationListener {
+
+ // visible for testing
+ final PrintStream printStream;
+
+ private int mockInvocationsCounter = 0;
+
+ public VerboseMockInvocationLogger() {
+ this(System.out);
+ }
+
+ public VerboseMockInvocationLogger(PrintStream printStream) {
+ this.printStream = printStream;
+ }
+
+ public void reportInvocation(MethodInvocationReport methodInvocationReport) {
+ printHeader();
+ printStubInfo(methodInvocationReport);
+ printInvocation(methodInvocationReport.getInvocation());
+ printReturnedValueOrThrowable(methodInvocationReport);
+ printFooter();
+ }
+
+ private void printReturnedValueOrThrowable(MethodInvocationReport methodInvocationReport) {
+ if (methodInvocationReport.threwException()) {
+ String message = methodInvocationReport.getThrowable().getMessage() == null ? "" : " with message " + methodInvocationReport.getThrowable().getMessage();
+ printlnIndented("has thrown: " + methodInvocationReport.getThrowable().getClass() + message);
+ } else {
+ String type = (methodInvocationReport.getReturnedValue() == null) ? "" : " (" + methodInvocationReport.getReturnedValue().getClass().getName() + ")";
+ printlnIndented("has returned: \"" + methodInvocationReport.getReturnedValue() + "\"" + type);
+ }
+ }
+
+ private void printStubInfo(MethodInvocationReport methodInvocationReport) {
+ if (methodInvocationReport.getLocationOfStubbing() != null) {
+ printlnIndented("stubbed: " + methodInvocationReport.getLocationOfStubbing());
+ }
+ }
+
+ private void printHeader() {
+ mockInvocationsCounter++;
+ printStream.println("############ Logging method invocation #" + mockInvocationsCounter + " on mock/spy ########");
+ }
+
+ private void printInvocation(DescribedInvocation invocation) {
+ printStream.println(invocation.toString());
+// printStream.println("Handling method call on a mock/spy.");
+ printlnIndented("invoked: " + invocation.getLocation().toString());
+ }
+
+ private void printFooter() {
+ printStream.println("");
+ }
+
+ private void printlnIndented(String message) {
+ printStream.println(" " + message);
+ }
+
+}
diff --git a/src/org/mockito/internal/debugging/WarningsCollector.java b/src/org/mockito/internal/debugging/WarningsCollector.java
new file mode 100644
index 0000000..6a870d4
--- /dev/null
+++ b/src/org/mockito/internal/debugging/WarningsCollector.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.UnusedStubsFinder;
+import org.mockito.internal.invocation.finder.AllInvocationsFinder;
+import org.mockito.internal.listeners.CollectCreatedMocks;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+import org.mockito.invocation.Invocation;
+
+import java.util.LinkedList;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class WarningsCollector {
+
+ List createdMocks;
+
+ public WarningsCollector() {
+ createdMocks = new LinkedList();
+ MockingProgress progress = new ThreadSafeMockingProgress();
+ progress.setListener(new CollectCreatedMocks(createdMocks));
+ }
+
+ public String getWarnings() {
+ List<Invocation> unused = new UnusedStubsFinder().find(createdMocks);
+ List<Invocation> all = new AllInvocationsFinder().find(createdMocks);
+ List<InvocationMatcher> allInvocationMatchers = InvocationMatcher.createFrom(all);
+
+ String warnings = new WarningsPrinterImpl(unused, allInvocationMatchers, false).print();
+
+ return warnings;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/debugging/WarningsFinder.java b/src/org/mockito/internal/debugging/WarningsFinder.java
new file mode 100644
index 0000000..08ffb3e
--- /dev/null
+++ b/src/org/mockito/internal/debugging/WarningsFinder.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class WarningsFinder {
+ private final List<Invocation> baseUnusedStubs;
+ private final List<InvocationMatcher> baseAllInvocations;
+
+ public WarningsFinder(List<Invocation> unusedStubs, List<InvocationMatcher> allInvocations) {
+ this.baseUnusedStubs = unusedStubs;
+ this.baseAllInvocations = allInvocations;
+ }
+
+ public void find(FindingsListener findingsListener) {
+ List<Invocation> unusedStubs = new LinkedList(this.baseUnusedStubs);
+ List<InvocationMatcher> allInvocations = new LinkedList(this.baseAllInvocations);
+
+ Iterator<Invocation> unusedIterator = unusedStubs.iterator();
+ while(unusedIterator.hasNext()) {
+ Invocation unused = unusedIterator.next();
+ Iterator<InvocationMatcher> unstubbedIterator = allInvocations.iterator();
+ while(unstubbedIterator.hasNext()) {
+ InvocationMatcher unstubbed = unstubbedIterator.next();
+ if(unstubbed.hasSimilarMethod(unused)) {
+ findingsListener.foundStubCalledWithDifferentArgs(unused, unstubbed);
+ unusedIterator.remove();
+ unstubbedIterator.remove();
+ }
+ }
+ }
+
+ for (Invocation i : unusedStubs) {
+ findingsListener.foundUnusedStub(i);
+ }
+
+ for (InvocationMatcher i : allInvocations) {
+ findingsListener.foundUnstubbed(i);
+ }
+ }
+}
diff --git a/src/org/mockito/internal/debugging/WarningsPrinterImpl.java b/src/org/mockito/internal/debugging/WarningsPrinterImpl.java
new file mode 100644
index 0000000..ab4c364
--- /dev/null
+++ b/src/org/mockito/internal/debugging/WarningsPrinterImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.debugging;
+
+import java.util.List;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.util.MockitoLogger;
+import org.mockito.internal.util.SimpleMockitoLogger;
+import org.mockito.invocation.Invocation;
+
+public class WarningsPrinterImpl {
+
+ private final boolean warnAboutUnstubbed;
+ private WarningsFinder finder;
+
+ public WarningsPrinterImpl(List<Invocation> unusedStubs, List<InvocationMatcher> unstubbedInvocations) {
+ this(unusedStubs, unstubbedInvocations, false);
+ }
+
+ public WarningsPrinterImpl(List<Invocation> unusedStubs, List<InvocationMatcher> allInvocations, boolean warnAboutUnstubbed) {
+ this(warnAboutUnstubbed, new WarningsFinder(unusedStubs, allInvocations));
+ }
+
+ WarningsPrinterImpl(boolean warnAboutUnstubbed, WarningsFinder finder) {
+ this.warnAboutUnstubbed = warnAboutUnstubbed;
+ this.finder = finder;
+ }
+
+ public void print(final MockitoLogger logger) {
+ finder.find(new LoggingListener(warnAboutUnstubbed, logger));
+ }
+
+ public String print() {
+ SimpleMockitoLogger logger = new SimpleMockitoLogger();
+ this.print(logger);
+ return logger.getLoggedInfo();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/debugging/package.html b/src/org/mockito/internal/debugging/package.html
new file mode 100644
index 0000000..13cee40
--- /dev/null
+++ b/src/org/mockito/internal/debugging/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Whatever helps in debugging failed tests
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java b/src/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java
new file mode 100644
index 0000000..272187a
--- /dev/null
+++ b/src/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.exceptions;
+
+public class ExceptionIncludingMockitoWarnings extends RuntimeException {
+ private static final long serialVersionUID = -5925150219446765679L;
+
+ public ExceptionIncludingMockitoWarnings(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+}
diff --git a/src/org/mockito/internal/exceptions/VerificationAwareInvocation.java b/src/org/mockito/internal/exceptions/VerificationAwareInvocation.java
new file mode 100644
index 0000000..adfdbc9
--- /dev/null
+++ b/src/org/mockito/internal/exceptions/VerificationAwareInvocation.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.exceptions;
+
+import org.mockito.invocation.DescribedInvocation;
+
+public interface VerificationAwareInvocation extends DescribedInvocation {
+
+ boolean isVerified();
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java b/src/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java
new file mode 100644
index 0000000..b3af5a7
--- /dev/null
+++ b/src/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.exceptions.stacktrace;
+
+import org.mockito.configuration.IMockitoConfiguration;
+import org.mockito.internal.configuration.GlobalConfiguration;
+
+import java.io.Serializable;
+
+public class ConditionalStackTraceFilter implements Serializable {
+ static final long serialVersionUID = -8085849703510292641L;
+
+ private IMockitoConfiguration config = new GlobalConfiguration();
+ private StackTraceFilter filter = new StackTraceFilter();
+
+ public void filter(Throwable throwable) {
+ if (!config.cleansStackTrace()) {
+ return;
+ }
+ StackTraceElement[] filtered = filter.filter(throwable.getStackTrace(), true);
+ throwable.setStackTrace(filtered);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java b/src/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java
new file mode 100644
index 0000000..84727c9
--- /dev/null
+++ b/src/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java
@@ -0,0 +1,16 @@
+package org.mockito.internal.exceptions.stacktrace;
+
+import org.mockito.exceptions.stacktrace.StackTraceCleaner;
+
+/**
+* by Szczepan Faber, created at: 7/29/12
+*/
+public class DefaultStackTraceCleaner implements StackTraceCleaner {
+ public boolean isOut(StackTraceElement e) {
+ boolean fromMockObject = e.getClassName().contains("$$EnhancerByMockitoWithCGLIB$$");
+ boolean fromOrgMockito = e.getClassName().startsWith("org.mockito.");
+ boolean isRunner = e.getClassName().startsWith("org.mockito.runners.");
+ boolean isInternalRunner = e.getClassName().startsWith("org.mockito.internal.runners.");
+ return (fromMockObject || fromOrgMockito) && !isRunner && !isInternalRunner;
+ }
+}
diff --git a/src/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java b/src/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java
new file mode 100644
index 0000000..b0d30e4
--- /dev/null
+++ b/src/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java
@@ -0,0 +1,14 @@
+package org.mockito.internal.exceptions.stacktrace;
+
+import org.mockito.exceptions.stacktrace.StackTraceCleaner;
+import org.mockito.plugins.StackTraceCleanerProvider;
+
+/**
+ * by Szczepan Faber, created at: 7/29/12
+ */
+public class DefaultStackTraceCleanerProvider implements StackTraceCleanerProvider {
+
+ public StackTraceCleaner getStackTraceCleaner(StackTraceCleaner defaultCleaner) {
+ return defaultCleaner;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java b/src/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java
new file mode 100644
index 0000000..a3e9d03
--- /dev/null
+++ b/src/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.exceptions.stacktrace;
+
+import org.mockito.exceptions.stacktrace.StackTraceCleaner;
+import org.mockito.internal.configuration.ClassPathLoader;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+public class StackTraceFilter implements Serializable {
+
+ static final long serialVersionUID = -5499819791513105700L;
+
+ private static StackTraceCleaner cleaner =
+ ClassPathLoader.getStackTraceCleanerProvider().getStackTraceCleaner(new DefaultStackTraceCleaner());
+
+ /**
+ * Example how the filter works (+/- means good/bad):
+ * [a+, b+, c-, d+, e+, f-, g+] -> [a+, b+, g+]
+ * Basically removes all bad from the middle. If any good are in the middle of bad those are also removed.
+ */
+ public StackTraceElement[] filter(StackTraceElement[] target, boolean keepTop) {
+ //TODO: profile
+ List<StackTraceElement> unfilteredStackTrace = Arrays.asList(target);
+
+ int lastBad = -1;
+ int firstBad = -1;
+ for (int i = 0; i < unfilteredStackTrace.size(); i++) {
+ if (!cleaner.isOut(unfilteredStackTrace.get(i))) {
+ continue;
+ }
+ lastBad = i;
+ if (firstBad == -1) {
+ firstBad = i;
+ }
+ }
+
+ List<StackTraceElement> top;
+ if (keepTop && firstBad != -1) {
+ top = unfilteredStackTrace.subList(0, firstBad);
+ } else {
+ top = new LinkedList<StackTraceElement>();
+ }
+
+ List<StackTraceElement> bottom = unfilteredStackTrace.subList(lastBad + 1, unfilteredStackTrace.size());
+ List<StackTraceElement> filtered = new ArrayList<StackTraceElement>(top);
+ filtered.addAll(bottom);
+ return filtered.toArray(new StackTraceElement[]{});
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/exceptions/stacktrace/package.html b/src/org/mockito/internal/exceptions/stacktrace/package.html
new file mode 100644
index 0000000..84b9ff9
--- /dev/null
+++ b/src/org/mockito/internal/exceptions/stacktrace/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Stack trace filtering / cleaning internal APIs.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/exceptions/util/ScenarioPrinter.java b/src/org/mockito/internal/exceptions/util/ScenarioPrinter.java
new file mode 100644
index 0000000..82259e6
--- /dev/null
+++ b/src/org/mockito/internal/exceptions/util/ScenarioPrinter.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.exceptions.util;
+
+import java.util.List;
+
+import org.mockito.internal.exceptions.VerificationAwareInvocation;
+
+public class ScenarioPrinter {
+
+ public String print(List<VerificationAwareInvocation> invocations) {
+ if (invocations.size() == 1) {
+ return "Actually, above is the only interaction with this mock.";
+ }
+ StringBuilder sb = new StringBuilder(
+ "***\n" +
+ "For your reference, here is the list of all invocations ([?] - means unverified).\n");
+
+ int counter = 0;
+ for (VerificationAwareInvocation i : invocations) {
+ sb.append(++counter + ". ");
+ if (!i.isVerified()) {
+ sb.append("[?]");
+ }
+ sb.append(i.getLocation() + "\n");
+ }
+ String scenario = sb.toString();
+ return scenario;
+ }
+
+}
diff --git a/src/org/mockito/internal/handler/InvocationNotifierHandler.java b/src/org/mockito/internal/handler/InvocationNotifierHandler.java
new file mode 100644
index 0000000..71030c4
--- /dev/null
+++ b/src/org/mockito/internal/handler/InvocationNotifierHandler.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.handler;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.listeners.NotifiedMethodInvocationReport;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.VoidMethodStubbable;
+
+import java.util.List;
+
+/**
+ * Handler, that call all listeners wanted for this mock, before delegating it
+ * to the parameterized handler.
+ *
+ * Also imposterize MockHandlerImpl, delegate all call of InternalMockHandler to the real mockHandler
+ */
+class InvocationNotifierHandler<T> implements MockHandler, InternalMockHandler<T> {
+
+ private List<InvocationListener> invocationListeners;
+ private InternalMockHandler<T> mockHandler;
+
+ public InvocationNotifierHandler(InternalMockHandler<T> mockHandler, MockCreationSettings settings) {
+ this.mockHandler = mockHandler;
+ this.invocationListeners = settings.getInvocationListeners();
+ }
+
+ public Object handle(Invocation invocation) throws Throwable {
+ try {
+ Object returnedValue = mockHandler.handle(invocation);
+ notifyMethodCall(invocation, returnedValue);
+ return returnedValue;
+ } catch (Throwable t){
+ notifyMethodCallException(invocation, t);
+ throw t;
+ }
+ }
+
+
+ private void notifyMethodCall(Invocation invocation, Object returnValue) {
+ for (InvocationListener listener : invocationListeners) {
+ try {
+ listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, returnValue));
+ } catch(Throwable listenerThrowable) {
+ new Reporter().invocationListenerThrewException(listener, listenerThrowable);
+ }
+ }
+ }
+
+ private void notifyMethodCallException(Invocation invocation, Throwable exception) {
+ for (InvocationListener listener : invocationListeners) {
+ try {
+ listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, exception));
+ } catch(Throwable listenerThrowable) {
+ new Reporter().invocationListenerThrewException(listener, listenerThrowable);
+ }
+ }
+ }
+
+ public MockCreationSettings getMockSettings() {
+ return mockHandler.getMockSettings();
+ }
+
+ public VoidMethodStubbable<T> voidMethodStubbable(T mock) {
+ return mockHandler.voidMethodStubbable(mock);
+ }
+
+ public void setAnswersForStubbing(List<Answer> answers) {
+ mockHandler.setAnswersForStubbing(answers);
+ }
+
+ public InvocationContainer getInvocationContainer() {
+ return mockHandler.getInvocationContainer();
+ }
+
+}
diff --git a/src/org/mockito/internal/handler/MockHandlerFactory.java b/src/org/mockito/internal/handler/MockHandlerFactory.java
new file mode 100644
index 0000000..4fef71b
--- /dev/null
+++ b/src/org/mockito/internal/handler/MockHandlerFactory.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.handler;
+
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.mock.MockCreationSettings;
+
+/**
+ * by Szczepan Faber, created at: 5/21/12
+ */
+public class MockHandlerFactory {
+
+ public InternalMockHandler create(MockCreationSettings settings) {
+ InternalMockHandler handler = new MockHandlerImpl(settings);
+ InternalMockHandler nullResultGuardian = new NullResultGuardian(handler);
+ InternalMockHandler notifier = new InvocationNotifierHandler(nullResultGuardian, settings);
+
+ return notifier;
+ }
+}
diff --git a/src/org/mockito/internal/handler/MockHandlerImpl.java b/src/org/mockito/internal/handler/MockHandlerImpl.java
new file mode 100644
index 0000000..a49c1a9
--- /dev/null
+++ b/src/org/mockito/internal/handler/MockHandlerImpl.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.handler;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.MatchersBinder;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+import org.mockito.internal.stubbing.*;
+import org.mockito.internal.verification.MockAwareVerificationMode;
+import org.mockito.internal.verification.VerificationDataImpl;
+import org.mockito.invocation.Invocation;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.VoidMethodStubbable;
+import org.mockito.verification.VerificationMode;
+
+import java.util.List;
+
+/**
+ * Invocation handler set on mock objects.
+ *
+ * @param <T>
+ * type of mock object to handle
+ */
+class MockHandlerImpl<T> implements InternalMockHandler<T> {
+
+ private static final long serialVersionUID = -2917871070982574165L;
+
+ InvocationContainerImpl invocationContainerImpl;
+ MatchersBinder matchersBinder = new MatchersBinder();
+ MockingProgress mockingProgress = new ThreadSafeMockingProgress();
+
+ private final MockCreationSettings mockSettings;
+
+ public MockHandlerImpl(MockCreationSettings mockSettings) {
+ this.mockSettings = mockSettings;
+ this.mockingProgress = new ThreadSafeMockingProgress();
+ this.matchersBinder = new MatchersBinder();
+ this.invocationContainerImpl = new InvocationContainerImpl(mockingProgress, mockSettings);
+ }
+
+ public Object handle(Invocation invocation) throws Throwable {
+ if (invocationContainerImpl.hasAnswersForStubbing()) {
+ // stubbing voids with stubVoid() or doAnswer() style
+ InvocationMatcher invocationMatcher = matchersBinder.bindMatchers(
+ mockingProgress.getArgumentMatcherStorage(),
+ invocation
+ );
+ invocationContainerImpl.setMethodForStubbing(invocationMatcher);
+ return null;
+ }
+ VerificationMode verificationMode = mockingProgress.pullVerificationMode();
+
+ InvocationMatcher invocationMatcher = matchersBinder.bindMatchers(
+ mockingProgress.getArgumentMatcherStorage(),
+ invocation
+ );
+
+ mockingProgress.validateState();
+
+ // if verificationMode is not null then someone is doing verify()
+ if (verificationMode != null) {
+ // We need to check if verification was started on the correct mock
+ // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)
+ if (((MockAwareVerificationMode) verificationMode).getMock() == invocation.getMock()) {
+ VerificationDataImpl data = createVerificationData(invocationContainerImpl, invocationMatcher);
+ verificationMode.verify(data);
+ return null;
+ } else {
+ // this means there is an invocation on a different mock. Re-adding verification mode
+ // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)
+ mockingProgress.verificationStarted(verificationMode);
+ }
+ }
+
+ // prepare invocation for stubbing
+ invocationContainerImpl.setInvocationForPotentialStubbing(invocationMatcher);
+ OngoingStubbingImpl<T> ongoingStubbing = new OngoingStubbingImpl<T>(invocationContainerImpl);
+ mockingProgress.reportOngoingStubbing(ongoingStubbing);
+
+ // look for existing answer for this invocation
+ StubbedInvocationMatcher stubbedInvocation = invocationContainerImpl.findAnswerFor(invocation);
+
+ if (stubbedInvocation != null) {
+ stubbedInvocation.captureArgumentsFrom(invocation);
+ return stubbedInvocation.answer(invocation);
+ } else {
+ Object ret = mockSettings.getDefaultAnswer().answer(invocation);
+
+ // redo setting invocation for potential stubbing in case of partial
+ // mocks / spies.
+ // Without it, the real method inside 'when' might have delegated
+ // to other self method and overwrite the intended stubbed method
+ // with a different one. The reset is required to avoid runtime exception that validates return type with stubbed method signature.
+ invocationContainerImpl.resetInvocationForPotentialStubbing(invocationMatcher);
+ return ret;
+ }
+ }
+
+ public VoidMethodStubbable<T> voidMethodStubbable(T mock) {
+ return new VoidMethodStubbableImpl<T>(mock, invocationContainerImpl);
+ }
+
+ public MockCreationSettings getMockSettings() {
+ return mockSettings;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setAnswersForStubbing(List<Answer> answers) {
+ invocationContainerImpl.setAnswersForStubbing(answers);
+ }
+
+ public InvocationContainer getInvocationContainer() {
+ return invocationContainerImpl;
+ }
+
+ private VerificationDataImpl createVerificationData(InvocationContainerImpl invocationContainerImpl, InvocationMatcher invocationMatcher) {
+ if (mockSettings.isStubOnly()) {
+ new Reporter().stubPassedToVerify(); // this throws an exception
+ }
+
+ return new VerificationDataImpl(invocationContainerImpl, invocationMatcher);
+ }
+}
+
diff --git a/src/org/mockito/internal/handler/NullResultGuardian.java b/src/org/mockito/internal/handler/NullResultGuardian.java
new file mode 100644
index 0000000..30b03df
--- /dev/null
+++ b/src/org/mockito/internal/handler/NullResultGuardian.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.handler;
+
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.progress.HandyReturnValues;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.invocation.Invocation;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.VoidMethodStubbable;
+
+import java.util.List;
+
+/**
+ * Protects the results from delegate MockHandler. Makes sure the results are valid.
+ *
+ * by Szczepan Faber, created at: 5/22/12
+ */
+class NullResultGuardian implements InternalMockHandler {
+ private final InternalMockHandler delegate;
+
+ public NullResultGuardian(InternalMockHandler delegate) {
+ this.delegate = delegate;
+ }
+
+ public Object handle(Invocation invocation) throws Throwable {
+ Object result = delegate.handle(invocation);
+ Class<?> returnType = invocation.getMethod().getReturnType();
+ if(result == null && returnType.isPrimitive()) {
+ //primitive values cannot be null
+ return new HandyReturnValues().returnFor(returnType);
+ } else {
+ return result;
+ }
+ }
+
+ //boring delegation:
+
+ public MockCreationSettings getMockSettings() {
+ return delegate.getMockSettings();
+ }
+
+ public VoidMethodStubbable voidMethodStubbable(Object mock) {
+ return delegate.voidMethodStubbable(mock);
+ }
+
+ public void setAnswersForStubbing(List answers) {
+ delegate.setAnswersForStubbing(answers);
+ }
+
+ public InvocationContainer getInvocationContainer() {
+ return delegate.getInvocationContainer();
+ }
+}
diff --git a/src/org/mockito/internal/invocation/ArgumentsComparator.java b/src/org/mockito/internal/invocation/ArgumentsComparator.java
new file mode 100644
index 0000000..416a40f
--- /dev/null
+++ b/src/org/mockito/internal/invocation/ArgumentsComparator.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.hamcrest.Matcher;
+import org.mockito.internal.matchers.MatcherDecorator;
+import org.mockito.internal.matchers.VarargMatcher;
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class ArgumentsComparator {
+ public boolean argumentsMatch(InvocationMatcher invocationMatcher, Invocation actual) {
+ Object[] actualArgs = actual.getArguments();
+ return argumentsMatch(invocationMatcher, actualArgs) || varArgsMatch(invocationMatcher, actual);
+ }
+
+ public boolean argumentsMatch(InvocationMatcher invocationMatcher, Object[] actualArgs) {
+ if (actualArgs.length != invocationMatcher.getMatchers().size()) {
+ return false;
+ }
+ for (int i = 0; i < actualArgs.length; i++) {
+ if (!invocationMatcher.getMatchers().get(i).matches(actualArgs[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ //ok, this method is a little bit messy but the vararg business unfortunately is messy...
+ private boolean varArgsMatch(InvocationMatcher invocationMatcher, Invocation actual) {
+ if (!actual.getMethod().isVarArgs()) {
+ //if the method is not vararg forget about it
+ return false;
+ }
+
+ //we must use raw arguments, not arguments...
+ Object[] rawArgs = actual.getRawArguments();
+ List<Matcher> matchers = invocationMatcher.getMatchers();
+
+ if (rawArgs.length != matchers.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < rawArgs.length; i++) {
+ Matcher m = matchers.get(i);
+ //it's a vararg because it's the last array in the arg list
+ if (rawArgs[i] != null && rawArgs[i].getClass().isArray() && i == rawArgs.length-1) {
+ Matcher actualMatcher;
+ //this is necessary as the framework often decorates matchers
+ if (m instanceof MatcherDecorator) {
+ actualMatcher = ((MatcherDecorator)m).getActualMatcher();
+ } else {
+ actualMatcher = m;
+ }
+ //this is very important to only allow VarargMatchers here. If you're not sure why remove it and run all tests.
+ if (!(actualMatcher instanceof VarargMatcher) || !actualMatcher.matches(rawArgs[i])) {
+ return false;
+ }
+ //it's not a vararg (i.e. some ordinary argument before varargs), just do the ordinary check
+ } else if (!m.matches(rawArgs[i])){
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/ArgumentsProcessor.java b/src/org/mockito/internal/invocation/ArgumentsProcessor.java
new file mode 100644
index 0000000..d0a6a5e
--- /dev/null
+++ b/src/org/mockito/internal/invocation/ArgumentsProcessor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.hamcrest.Matcher;
+import org.mockito.internal.matchers.ArrayEquals;
+import org.mockito.internal.matchers.Equals;
+import org.mockito.internal.util.collections.ArrayUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * by Szczepan Faber, created at: 3/31/12
+ */
+public class ArgumentsProcessor {
+ // expands array varArgs that are given by runtime (1, [a, b]) into true
+ // varArgs (1, a, b);
+ public static Object[] expandVarArgs(final boolean isVarArgs, final Object[] args) {
+ if (!isVarArgs || new ArrayUtils().isEmpty(args) || args[args.length - 1] != null && !args[args.length - 1].getClass().isArray()) {
+ return args == null ? new Object[0] : args;
+ }
+
+ final int nonVarArgsCount = args.length - 1;
+ Object[] varArgs;
+ if (args[nonVarArgsCount] == null) {
+ // in case someone deliberately passed null varArg array
+ varArgs = new Object[] { null };
+ } else {
+ varArgs = ArrayEquals.createObjectArray(args[nonVarArgsCount]);
+ }
+ final int varArgsCount = varArgs.length;
+ Object[] newArgs = new Object[nonVarArgsCount + varArgsCount];
+ System.arraycopy(args, 0, newArgs, 0, nonVarArgsCount);
+ System.arraycopy(varArgs, 0, newArgs, nonVarArgsCount, varArgsCount);
+ return newArgs;
+ }
+
+ public static List<Matcher> argumentsToMatchers(Object[] arguments) {
+ List<Matcher> matchers = new ArrayList<Matcher>(arguments.length);
+ for (Object arg : arguments) {
+ if (arg != null && arg.getClass().isArray()) {
+ matchers.add(new ArrayEquals(arg));
+ } else {
+ matchers.add(new Equals(arg));
+ }
+ }
+ return matchers;
+ }
+}
diff --git a/src/org/mockito/internal/invocation/CapturesArgumensFromInvocation.java b/src/org/mockito/internal/invocation/CapturesArgumensFromInvocation.java
new file mode 100644
index 0000000..2e32bdd
--- /dev/null
+++ b/src/org/mockito/internal/invocation/CapturesArgumensFromInvocation.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+
+import org.mockito.invocation.Invocation;
+
+public interface CapturesArgumensFromInvocation {
+
+ void captureArgumentsFrom(Invocation i);
+
+}
diff --git a/src/org/mockito/internal/invocation/InvocationImpl.java b/src/org/mockito/internal/invocation/InvocationImpl.java
new file mode 100644
index 0000000..6b6f8c8
--- /dev/null
+++ b/src/org/mockito/internal/invocation/InvocationImpl.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.internal.exceptions.VerificationAwareInvocation;
+import org.mockito.internal.invocation.realmethod.RealMethod;
+import org.mockito.internal.reporting.PrintSettings;
+import org.mockito.invocation.*;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+/**
+ * Method call on a mock object.
+ * <p>
+ * Contains sequence number which should be globally unique and is used for
+ * verification in order.
+ * <p>
+ * Contains stack trace of invocation
+ */
+@SuppressWarnings("unchecked")
+public class InvocationImpl implements Invocation, VerificationAwareInvocation {
+
+ private static final long serialVersionUID = 8240069639250980199L;
+ private final int sequenceNumber;
+ private final Object mock;
+ private final MockitoMethod method;
+ private final Object[] arguments;
+ private final Object[] rawArguments;
+
+ private final Location location;
+ private boolean verified;
+ private boolean isIgnoredForVerification;
+
+ final RealMethod realMethod;
+ private StubInfo stubInfo;
+
+ public InvocationImpl(Object mock, MockitoMethod mockitoMethod, Object[] args, int sequenceNumber, RealMethod realMethod) {
+ this.method = mockitoMethod;
+ this.mock = mock;
+ this.realMethod = realMethod;
+ this.arguments = ArgumentsProcessor.expandVarArgs(mockitoMethod.isVarArgs(), args);
+ this.rawArguments = args;
+ this.sequenceNumber = sequenceNumber;
+ this.location = new LocationImpl();
+ }
+
+ public Object getMock() {
+ return mock;
+ }
+
+ public Method getMethod() {
+ return method.getJavaMethod();
+ }
+
+ public Object[] getArguments() {
+ return arguments;
+ }
+
+ public boolean isVerified() {
+ return verified || isIgnoredForVerification;
+ }
+
+ public int getSequenceNumber() {
+ return sequenceNumber;
+ }
+
+ public boolean equals(Object o) {
+ if (o == null || !o.getClass().equals(this.getClass())) {
+ return false;
+ }
+
+ InvocationImpl other = (InvocationImpl) o;
+
+ return this.mock.equals(other.mock) && this.method.equals(other.method) && this.equalArguments(other.arguments);
+ }
+
+ private boolean equalArguments(Object[] arguments) {
+ return Arrays.equals(arguments, this.arguments);
+ }
+
+ @Override
+ public int hashCode() {
+ return 1;
+ }
+
+ public String toString() {
+ return new PrintSettings().print(ArgumentsProcessor.argumentsToMatchers(getArguments()), this);
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public Object[] getRawArguments() {
+ return this.rawArguments;
+ }
+
+ public Object callRealMethod() throws Throwable {
+ if (this.getMethod().getDeclaringClass().isInterface()) {
+ new Reporter().cannotCallRealMethodOnInterface();
+ }
+ return realMethod.invoke(mock, rawArguments);
+ }
+
+ public void markVerified() {
+ this.verified = true;
+ }
+
+ public StubInfo stubInfo() {
+ return stubInfo;
+ }
+
+ public void markStubbed(StubInfo stubInfo) {
+ this.stubInfo = stubInfo;
+ }
+
+ public boolean isIgnoredForVerification() {
+ return isIgnoredForVerification;
+ }
+
+ public void ignoreForVerification() {
+ isIgnoredForVerification = true;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/InvocationMarker.java b/src/org/mockito/internal/invocation/InvocationMarker.java
new file mode 100644
index 0000000..4df2e3d
--- /dev/null
+++ b/src/org/mockito/internal/invocation/InvocationMarker.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import java.util.List;
+
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+
+public class InvocationMarker {
+
+ public void markVerified(List<Invocation> invocations, CapturesArgumensFromInvocation wanted) {
+ for (Invocation invocation : invocations) {
+ markVerified(invocation, wanted);
+ }
+ }
+
+ public void markVerified(Invocation invocation, CapturesArgumensFromInvocation wanted) {
+ invocation.markVerified();
+ wanted.captureArgumentsFrom(invocation);
+ }
+
+ public void markVerifiedInOrder(List<Invocation> chunk, CapturesArgumensFromInvocation wanted, InOrderContext context) {
+ markVerified(chunk, wanted);
+
+ for (Invocation i : chunk) {
+ context.markVerified(i);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/InvocationMatcher.java b/src/org/mockito/internal/invocation/InvocationMatcher.java
new file mode 100644
index 0000000..86e83ca
--- /dev/null
+++ b/src/org/mockito/internal/invocation/InvocationMatcher.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.hamcrest.Matcher;
+import org.mockito.internal.matchers.CapturesArguments;
+import org.mockito.internal.matchers.MatcherDecorator;
+import org.mockito.internal.matchers.VarargMatcher;
+import org.mockito.internal.reporting.PrintSettings;
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+
+@SuppressWarnings("unchecked")
+public class InvocationMatcher implements DescribedInvocation, CapturesArgumensFromInvocation, Serializable {
+
+ private static final long serialVersionUID = -3047126096857467610L;
+ private final Invocation invocation;
+ private final List<Matcher> matchers;
+
+ public InvocationMatcher(Invocation invocation, List<Matcher> matchers) {
+ this.invocation = invocation;
+ if (matchers.isEmpty()) {
+ this.matchers = ArgumentsProcessor.argumentsToMatchers(invocation.getArguments());
+ } else {
+ this.matchers = matchers;
+ }
+ }
+
+ public InvocationMatcher(Invocation invocation) {
+ this(invocation, Collections.<Matcher>emptyList());
+ }
+
+ public Method getMethod() {
+ return invocation.getMethod();
+ }
+
+ public Invocation getInvocation() {
+ return this.invocation;
+ }
+
+ public List<Matcher> getMatchers() {
+ return this.matchers;
+ }
+
+ public String toString() {
+ return new PrintSettings().print(matchers, invocation);
+ }
+
+ public boolean matches(Invocation actual) {
+ return invocation.getMock().equals(actual.getMock())
+ && hasSameMethod(actual)
+ && new ArgumentsComparator().argumentsMatch(this, actual);
+ }
+
+ private boolean safelyArgumentsMatch(Object[] actualArgs) {
+ try {
+ return new ArgumentsComparator().argumentsMatch(this, actualArgs);
+ } catch (Throwable t) {
+ return false;
+ }
+ }
+
+ /**
+ * similar means the same method name, same mock, unverified
+ * and: if arguments are the same cannot be overloaded
+ */
+ public boolean hasSimilarMethod(Invocation candidate) {
+ String wantedMethodName = getMethod().getName();
+ String currentMethodName = candidate.getMethod().getName();
+
+ final boolean methodNameEquals = wantedMethodName.equals(currentMethodName);
+ final boolean isUnverified = !candidate.isVerified();
+ final boolean mockIsTheSame = getInvocation().getMock() == candidate.getMock();
+ final boolean methodEquals = hasSameMethod(candidate);
+
+ if (!methodNameEquals || !isUnverified || !mockIsTheSame) {
+ return false;
+ }
+
+ final boolean overloadedButSameArgs = !methodEquals && safelyArgumentsMatch(candidate.getArguments());
+
+ return !overloadedButSameArgs;
+ }
+
+ public boolean hasSameMethod(Invocation candidate) {
+ //not using method.equals() for 1 good reason:
+ //sometimes java generates forwarding methods when generics are in play see JavaGenericsForwardingMethodsTest
+ Method m1 = invocation.getMethod();
+ Method m2 = candidate.getMethod();
+
+ if (m1.getName() != null && m1.getName().equals(m2.getName())) {
+ /* Avoid unnecessary cloning */
+ Class[] params1 = m1.getParameterTypes();
+ Class[] params2 = m2.getParameterTypes();
+ if (params1.length == params2.length) {
+ for (int i = 0; i < params1.length; i++) {
+ if (params1[i] != params2[i])
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Location getLocation() {
+ return invocation.getLocation();
+ }
+
+ public void captureArgumentsFrom(Invocation invocation) {
+ for (int position = 0; position < matchers.size(); position++) {
+ Matcher m = matchers.get(position);
+ if (m instanceof CapturesArguments && invocation.getArguments().length > position) {
+ if(isVariableArgument(invocation, position) && isVarargMatcher(m)) {
+ ((CapturesArguments) m).captureFrom(invocation.getRawArguments()[position]);
+ } else {
+ ((CapturesArguments) m).captureFrom(invocation.getArguments()[position]);
+ }
+ }
+ }
+ }
+
+ private boolean isVarargMatcher(Matcher matcher) {
+ Matcher actualMatcher = matcher;
+ if (actualMatcher instanceof MatcherDecorator) {
+ actualMatcher = ((MatcherDecorator) actualMatcher).getActualMatcher();
+ }
+ return actualMatcher instanceof VarargMatcher;
+ }
+
+ private boolean isVariableArgument(Invocation invocation, int position) {
+ return invocation.getRawArguments().length - 1 == position
+ && invocation.getRawArguments()[position] != null
+ && invocation.getRawArguments()[position].getClass().isArray()
+ && invocation.getMethod().isVarArgs();
+ }
+
+ public static List<InvocationMatcher> createFrom(List<Invocation> invocations) {
+ LinkedList<InvocationMatcher> out = new LinkedList<InvocationMatcher>();
+
+ for (Invocation i : invocations) {
+ out.add(new InvocationMatcher(i));
+ }
+
+ return out;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/InvocationsFinder.java b/src/org/mockito/internal/invocation/InvocationsFinder.java
new file mode 100644
index 0000000..b88162b
--- /dev/null
+++ b/src/org/mockito/internal/invocation/InvocationsFinder.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.mockito.internal.util.collections.ListUtil;
+import org.mockito.internal.util.collections.ListUtil.Filter;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+
+public class InvocationsFinder {
+
+ public List<Invocation> findInvocations(List<Invocation> invocations, InvocationMatcher wanted) {
+ return ListUtil.filter(invocations, new RemoveNotMatching(wanted));
+ }
+
+ public List<Invocation> findAllMatchingUnverifiedChunks(List<Invocation> invocations, InvocationMatcher wanted, InOrderContext orderingContext) {
+ List<Invocation> unverified = removeVerifiedInOrder(invocations, orderingContext);
+ return ListUtil.filter(unverified, new RemoveNotMatching(wanted));
+ }
+
+ /**
+ * some examples how it works:
+ *
+ * Given invocations sequence:
+ * 1,1,2,1
+ *
+ * if wanted is 1 and mode is times(2) then returns
+ * 1,1
+ *
+ * if wanted is 1 and mode is atLeast() then returns
+ * 1,1,1
+ *
+ * if wanted is 1 and mode is times(x), where x != 2 then returns
+ * 1,1,1
+ */
+ public List<Invocation> findMatchingChunk(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount, InOrderContext context) {
+ List<Invocation> unverified = removeVerifiedInOrder(invocations, context);
+ List<Invocation> firstChunk = getFirstMatchingChunk(wanted, unverified);
+
+ if (wantedCount != firstChunk.size()) {
+ return this.findAllMatchingUnverifiedChunks(invocations, wanted, context);
+ } else {
+ return firstChunk;
+ }
+ }
+
+ private List<Invocation> getFirstMatchingChunk(InvocationMatcher wanted, List<Invocation> unverified) {
+ List<Invocation> firstChunk = new LinkedList<Invocation>();
+ for (Invocation invocation : unverified) {
+ if (wanted.matches(invocation)) {
+ firstChunk.add(invocation);
+ } else if (!firstChunk.isEmpty()) {
+ break;
+ }
+ }
+ return firstChunk;
+ }
+
+ public Invocation findFirstMatchingUnverifiedInvocation( List<Invocation> invocations, InvocationMatcher wanted, InOrderContext context ){
+ for( Invocation invocation : removeVerifiedInOrder( invocations, context )){
+ if( wanted.matches( invocation )){
+ return invocation;
+ }
+ }
+ return null;
+ }
+
+ public Invocation findSimilarInvocation(List<Invocation> invocations, InvocationMatcher wanted) {
+ Invocation firstSimilar = null;
+ for (Invocation invocation : invocations) {
+ if (!wanted.hasSimilarMethod(invocation)) {
+ continue;
+ }
+ if (firstSimilar == null) {
+ firstSimilar = invocation;
+ }
+ if (wanted.hasSameMethod(invocation)) {
+ return invocation;
+ }
+ }
+
+ return firstSimilar;
+ }
+
+ public Invocation findFirstUnverified(List<Invocation> invocations) {
+ return findFirstUnverified(invocations, null);
+ }
+
+ Invocation findFirstUnverified(List<Invocation> invocations, Object mock) {
+ for (Invocation i : invocations) {
+ boolean mockIsValid = mock == null || mock == i.getMock();
+ if (!i.isVerified() && mockIsValid) {
+ return i;
+ }
+ }
+ return null;
+ }
+
+ public Location getLastLocation(List<Invocation> invocations) {
+ if (invocations.isEmpty()) {
+ return null;
+ } else {
+ Invocation last = invocations.get(invocations.size() - 1);
+ return last.getLocation();
+ }
+ }
+
+ public Invocation findPreviousVerifiedInOrder(List<Invocation> invocations, InOrderContext context) {
+ LinkedList<Invocation> verifiedOnly = ListUtil.filter(invocations, new RemoveUnverifiedInOrder(context));
+
+ if (verifiedOnly.isEmpty()) {
+ return null;
+ } else {
+ return verifiedOnly.getLast();
+ }
+ }
+
+ private List<Invocation> removeVerifiedInOrder(List<Invocation> invocations, InOrderContext orderingContext) {
+ List<Invocation> unverified = new LinkedList<Invocation>();
+ for (Invocation i : invocations) {
+ if (orderingContext.isVerified(i)) {
+ unverified.clear();
+ } else {
+ unverified.add(i);
+ }
+ }
+ return unverified;
+ }
+
+ private class RemoveNotMatching implements Filter<Invocation> {
+ private final InvocationMatcher wanted;
+
+ private RemoveNotMatching(InvocationMatcher wanted) {
+ this.wanted = wanted;
+ }
+
+ public boolean isOut(Invocation invocation) {
+ return !wanted.matches(invocation);
+ }
+ }
+
+ private class RemoveUnverifiedInOrder implements Filter<Invocation> {
+ private final InOrderContext orderingContext;
+
+ public RemoveUnverifiedInOrder(InOrderContext orderingContext) {
+ this.orderingContext = orderingContext;
+ }
+
+ public boolean isOut(Invocation invocation) {
+ return !orderingContext.isVerified(invocation);
+ }
+ }
+
+ /**
+ * i3 is unverified here:
+ *
+ * i1, i2, i3
+ * v
+ *
+ * all good here:
+ *
+ * i1, i2, i3
+ * v v
+ *
+ * @param context
+ * @param orderedInvocations
+ */
+ public Invocation findFirstUnverifiedInOrder(InOrderContext context, List<Invocation> orderedInvocations) {
+ Invocation candidate = null;
+ for(Invocation i : orderedInvocations) {
+ if (!context.isVerified(i)) {
+ candidate = candidate != null ? candidate : i;
+ } else {
+ candidate = null;
+ }
+ }
+ return candidate;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/MatchersBinder.java b/src/org/mockito/internal/invocation/MatchersBinder.java
new file mode 100644
index 0000000..c40d3f7
--- /dev/null
+++ b/src/org/mockito/internal/invocation/MatchersBinder.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import org.hamcrest.Matcher;
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.matchers.LocalizedMatcher;
+import org.mockito.internal.progress.ArgumentMatcherStorage;
+import org.mockito.invocation.Invocation;
+
+import java.io.Serializable;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class MatchersBinder implements Serializable {
+
+ private static final long serialVersionUID = -311433939339443463L;
+
+ public InvocationMatcher bindMatchers(ArgumentMatcherStorage argumentMatcherStorage, Invocation invocation) {
+ List<LocalizedMatcher> lastMatchers = argumentMatcherStorage.pullLocalizedMatchers();
+ validateMatchers(invocation, lastMatchers);
+
+ InvocationMatcher invocationWithMatchers = new InvocationMatcher(invocation, (List<Matcher>)(List) lastMatchers);
+ return invocationWithMatchers;
+ }
+
+ private void validateMatchers(Invocation invocation, List<LocalizedMatcher> lastMatchers) {
+ if (!lastMatchers.isEmpty()) {
+ int recordedMatchersSize = lastMatchers.size();
+ int expectedMatchersSize = invocation.getArguments().length;
+ if (expectedMatchersSize != recordedMatchersSize) {
+ new Reporter().invalidUseOfMatchers(expectedMatchersSize, lastMatchers);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/MockitoMethod.java b/src/org/mockito/internal/invocation/MockitoMethod.java
new file mode 100644
index 0000000..09ea414
--- /dev/null
+++ b/src/org/mockito/internal/invocation/MockitoMethod.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import java.lang.reflect.Method;
+
+public interface MockitoMethod {
+
+ public String getName();
+
+ public Class<?> getReturnType();
+
+ public Class<?>[] getParameterTypes();
+
+ public Class<?>[] getExceptionTypes();
+
+ public boolean isVarArgs();
+
+ public Method getJavaMethod();
+}
diff --git a/src/org/mockito/internal/invocation/SerializableMethod.java b/src/org/mockito/internal/invocation/SerializableMethod.java
new file mode 100644
index 0000000..652bf6b
--- /dev/null
+++ b/src/org/mockito/internal/invocation/SerializableMethod.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import org.mockito.exceptions.base.MockitoException;
+
+public class SerializableMethod implements Serializable, MockitoMethod {
+
+ private static final long serialVersionUID = 6005610965006048445L;
+
+ private Class<?> declaringClass;
+ private String methodName;
+ private Class<?>[] parameterTypes;
+ private Class<?> returnType;
+ private Class<?>[] exceptionTypes;
+ private boolean isVarArgs;
+
+ public SerializableMethod(Method method) {
+ declaringClass = method.getDeclaringClass();
+ methodName = method.getName();
+ parameterTypes = method.getParameterTypes();
+ returnType = method.getReturnType();
+ exceptionTypes = method.getExceptionTypes();
+ isVarArgs = method.isVarArgs();
+ }
+
+ public String getName() {
+ return methodName;
+ }
+
+ public Class<?> getReturnType() {
+ return returnType;
+ }
+
+ public Class<?>[] getParameterTypes() {
+ return parameterTypes;
+ }
+
+ public Class<?>[] getExceptionTypes() {
+ return exceptionTypes;
+ }
+
+ public boolean isVarArgs() {
+ return isVarArgs;
+ }
+
+ public Method getJavaMethod() {
+ try {
+ return declaringClass.getDeclaredMethod(methodName, parameterTypes);
+ } catch (SecurityException e) {
+ String message = String.format(
+ "The method %1$s.%2$s is probably private or protected and cannot be mocked.\n" +
+ "Please report this as a defect with an example of how to reproduce it.", declaringClass, methodName);
+ throw new MockitoException(message, e);
+ } catch (NoSuchMethodException e) {
+ String message = String.format(
+ "The method %1$s.%2$s does not exists and you should not get to this point.\n" +
+ "Please report this as a defect with an example of how to reproduce it.", declaringClass, methodName);
+ throw new MockitoException(message, e);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return 1;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SerializableMethod other = (SerializableMethod) obj;
+ if (declaringClass == null) {
+ if (other.declaringClass != null)
+ return false;
+ } else if (!declaringClass.equals(other.declaringClass))
+ return false;
+ if (methodName == null) {
+ if (other.methodName != null)
+ return false;
+ } else if (!methodName.equals(other.methodName))
+ return false;
+ if (!Arrays.equals(parameterTypes, other.parameterTypes))
+ return false;
+ if (returnType == null) {
+ if (other.returnType != null)
+ return false;
+ } else if (!returnType.equals(other.returnType))
+ return false;
+ return true;
+ }
+}
diff --git a/src/org/mockito/internal/invocation/StubInfoImpl.java b/src/org/mockito/internal/invocation/StubInfoImpl.java
new file mode 100644
index 0000000..cdd245e
--- /dev/null
+++ b/src/org/mockito/internal/invocation/StubInfoImpl.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation;
+
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Location;
+import org.mockito.invocation.StubInfo;
+
+import java.io.Serializable;
+
+public class StubInfoImpl implements StubInfo, Serializable {
+ private static final long serialVersionUID = 2125827349332068867L;
+ private DescribedInvocation stubbedAt;
+
+ public StubInfoImpl(DescribedInvocation stubbedAt) {
+ this.stubbedAt = stubbedAt;
+ }
+
+ public Location stubbedAt() {
+ return stubbedAt.getLocation();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/UnusedStubsFinder.java b/src/org/mockito/internal/invocation/UnusedStubsFinder.java
new file mode 100644
index 0000000..451dcfb
--- /dev/null
+++ b/src/org/mockito/internal/invocation/UnusedStubsFinder.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation;
+
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.stubbing.StubbedInvocationMatcher;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.Invocation;
+
+import java.util.*;
+
+public class UnusedStubsFinder {
+
+ /**
+ * Finds all unused stubs for given mocks
+ *
+ * @param mocks
+ */
+ public List<Invocation> find(List<?> mocks) {
+ List<Invocation> unused = new LinkedList<Invocation>();
+ for (Object mock : mocks) {
+ InternalMockHandler<Object> handler = new MockUtil().getMockHandler(mock);
+ List<StubbedInvocationMatcher> fromSingleMock = handler.getInvocationContainer().getStubbedInvocations();
+ for(StubbedInvocationMatcher s : fromSingleMock) {
+ if (!s.wasUsed()) {
+ unused.add(s.getInvocation());
+ }
+ }
+ }
+ return unused;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/finder/AllInvocationsFinder.java b/src/org/mockito/internal/invocation/finder/AllInvocationsFinder.java
new file mode 100644
index 0000000..bcc9fb3
--- /dev/null
+++ b/src/org/mockito/internal/invocation/finder/AllInvocationsFinder.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation.finder;
+
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.Invocation;
+
+import java.util.*;
+
+public class AllInvocationsFinder {
+
+ /**
+ * gets all invocations from mocks. Invocations are ordered earlier first.
+ *
+ * @param mocks mocks
+ * @return invocations
+ */
+ public List<Invocation> find(List<?> mocks) {
+ Set<Invocation> invocationsInOrder = new TreeSet<Invocation>(new SequenceNumberComparator());
+ for (Object mock : mocks) {
+ InternalMockHandler<Object> handler = new MockUtil().getMockHandler(mock);
+ List<Invocation> fromSingleMock = handler.getInvocationContainer().getInvocations();
+ invocationsInOrder.addAll(fromSingleMock);
+ }
+
+ return new LinkedList<Invocation>(invocationsInOrder);
+ }
+
+ private final class SequenceNumberComparator implements Comparator<Invocation> {
+ public int compare(Invocation o1, Invocation o2) {
+ return Integer.valueOf(o1.getSequenceNumber()).compareTo(o2.getSequenceNumber());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java b/src/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java
new file mode 100644
index 0000000..ae25481
--- /dev/null
+++ b/src/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.invocation.finder;
+
+import org.mockito.internal.util.collections.ListUtil;
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+/**
+ * Author: Szczepan Faber, created at: 4/3/11
+ */
+public class VerifiableInvocationsFinder {
+
+ public List<Invocation> find(List<?> mocks) {
+ List<Invocation> invocations = new AllInvocationsFinder().find(mocks);
+ return ListUtil.filter(invocations, new RemoveIgnoredForVerification());
+ }
+
+ static class RemoveIgnoredForVerification implements ListUtil.Filter<Invocation>{
+ public boolean isOut(Invocation i) {
+ return i.isIgnoredForVerification();
+ }
+ }
+}
diff --git a/src/org/mockito/internal/invocation/package.html b/src/org/mockito/internal/invocation/package.html
new file mode 100644
index 0000000..4ed1db4
--- /dev/null
+++ b/src/org/mockito/internal/invocation/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Invocation and related classes.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/invocation/realmethod/RealMethod.java b/src/org/mockito/internal/invocation/realmethod/RealMethod.java
new file mode 100644
index 0000000..1812c4b
--- /dev/null
+++ b/src/org/mockito/internal/invocation/realmethod/RealMethod.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.invocation.realmethod;
+
+
+public interface RealMethod {
+
+ Object invoke(Object target, Object[] arguments) throws Throwable;
+
+}
diff --git a/src/org/mockito/internal/invocation/realmethod/package.html b/src/org/mockito/internal/invocation/realmethod/package.html
new file mode 100644
index 0000000..d89c54f
--- /dev/null
+++ b/src/org/mockito/internal/invocation/realmethod/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+implementations of real method calls
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/junit/JUnitTool.java b/src/org/mockito/internal/junit/JUnitTool.java
new file mode 100644
index 0000000..5d9c53b
--- /dev/null
+++ b/src/org/mockito/internal/junit/JUnitTool.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.junit;
+
+import org.mockito.exceptions.verification.ArgumentsAreDifferent;
+
+public class JUnitTool {
+
+ private static boolean hasJUnit;
+
+ static {
+ try {
+ Class.forName("junit.framework.ComparisonFailure");
+ hasJUnit = true;
+ } catch (Throwable t) {
+ hasJUnit = false;
+ }
+ }
+
+ public static boolean hasJUnit() {
+ return hasJUnit;
+ }
+
+ public static AssertionError createArgumentsAreDifferentException(String message, String wanted, String actual) {
+ try {
+ Class<?> clazz = Class.forName("org.mockito.exceptions.verification.junit.ArgumentsAreDifferent");
+ AssertionError throwable = (AssertionError) clazz.getConstructors()[0].newInstance(message, wanted, actual);
+ return throwable;
+ } catch (Throwable t) {
+// throw the default exception in case of problems
+ return new ArgumentsAreDifferent(message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/listeners/CollectCreatedMocks.java b/src/org/mockito/internal/listeners/CollectCreatedMocks.java
new file mode 100644
index 0000000..6592fd8
--- /dev/null
+++ b/src/org/mockito/internal/listeners/CollectCreatedMocks.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.listeners;
+
+import org.mockito.MockSettings;
+
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class CollectCreatedMocks implements MockingStartedListener {
+
+ private List toBeFilled;
+
+ public CollectCreatedMocks(List toBeFilled) {
+ this.toBeFilled = toBeFilled;
+ }
+
+ public void mockingStarted(Object mock, Class classToMock) {
+ toBeFilled.add(mock);
+ }
+}
diff --git a/src/org/mockito/internal/listeners/MockingProgressListener.java b/src/org/mockito/internal/listeners/MockingProgressListener.java
new file mode 100644
index 0000000..403088c
--- /dev/null
+++ b/src/org/mockito/internal/listeners/MockingProgressListener.java
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.listeners;
+
+public interface MockingProgressListener {
+}
diff --git a/src/org/mockito/internal/listeners/MockingStartedListener.java b/src/org/mockito/internal/listeners/MockingStartedListener.java
new file mode 100644
index 0000000..fd5cbe5
--- /dev/null
+++ b/src/org/mockito/internal/listeners/MockingStartedListener.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.listeners;
+
+import org.mockito.MockSettings;
+
+@SuppressWarnings("unchecked")
+public interface MockingStartedListener extends MockingProgressListener {
+
+ void mockingStarted(Object mock, Class classToMock);
+}
diff --git a/src/org/mockito/internal/listeners/NotifiedMethodInvocationReport.java b/src/org/mockito/internal/listeners/NotifiedMethodInvocationReport.java
new file mode 100644
index 0000000..f1eca81
--- /dev/null
+++ b/src/org/mockito/internal/listeners/NotifiedMethodInvocationReport.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.listeners;
+
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.Invocation;
+import org.mockito.listeners.MethodInvocationReport;
+
+/**
+ * Report on a method call
+ */
+public class NotifiedMethodInvocationReport implements MethodInvocationReport {
+ private final Invocation invocation;
+ private Object returnedValue;
+ private Throwable throwable;
+
+
+ /**
+ * Build a new {@link org.mockito.listeners.MethodInvocationReport} with a return value.
+ *
+ *
+ * @param invocation Information on the method call
+ * @param returnedValue The value returned by the method invocation
+ */
+ public NotifiedMethodInvocationReport(Invocation invocation, Object returnedValue) {
+ this.invocation = invocation;
+ this.returnedValue = returnedValue;
+ }
+
+ /**
+ * Build a new {@link org.mockito.listeners.MethodInvocationReport} with a return value.
+ *
+ *
+ * @param invocation Information on the method call
+ * @param throwable Tha throwable raised by the method invocation
+ */
+ public NotifiedMethodInvocationReport(Invocation invocation, Throwable throwable) {
+ this.invocation = invocation;
+ this.throwable = throwable;
+ }
+
+ public DescribedInvocation getInvocation() {
+ return invocation;
+ }
+
+ public Object getReturnedValue() {
+ return returnedValue;
+ }
+
+ public Throwable getThrowable() {
+ return throwable;
+ }
+
+ public boolean threwException() {
+ return throwable != null;
+ }
+
+ public String getLocationOfStubbing() {
+ return (invocation.stubInfo() == null) ? null : invocation.stubInfo().stubbedAt().toString();
+ }
+
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ NotifiedMethodInvocationReport that = (NotifiedMethodInvocationReport) o;
+
+ if (invocation != null ? !invocation.equals(that.invocation) : that.invocation != null) return false;
+ if (returnedValue != null ? !returnedValue.equals(that.returnedValue) : that.returnedValue != null)
+ return false;
+ if (throwable != null ? !throwable.equals(that.throwable) : that.throwable != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = invocation != null ? invocation.hashCode() : 0;
+ result = 31 * result + (returnedValue != null ? returnedValue.hashCode() : 0);
+ result = 31 * result + (throwable != null ? throwable.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/org/mockito/internal/matchers/And.java b/src/org/mockito/internal/matchers/And.java
new file mode 100644
index 0000000..4ff068a
--- /dev/null
+++ b/src/org/mockito/internal/matchers/And.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.mockito.ArgumentMatcher;
+
+@SuppressWarnings("unchecked")
+public class And extends ArgumentMatcher implements Serializable {
+
+ private static final long serialVersionUID = -4624719625691177501L;
+ private final List<Matcher> matchers;
+
+ public And(List<Matcher> matchers) {
+ this.matchers = matchers;
+ }
+
+ public boolean matches(Object actual) {
+ for (Matcher matcher : matchers) {
+ if (!matcher.matches(actual)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("and(");
+ for (Iterator<Matcher> it = matchers.iterator(); it.hasNext();) {
+ it.next().describeTo(description);
+ if (it.hasNext()) {
+ description.appendText(", ");
+ }
+ }
+ description.appendText(")");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/Any.java b/src/org/mockito/internal/matchers/Any.java
new file mode 100644
index 0000000..1876b38
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Any.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+@SuppressWarnings("unchecked")
+public class Any extends ArgumentMatcher implements Serializable {
+
+ private static final long serialVersionUID = -4062420125651019029L;
+ public static final Any ANY = new Any();
+
+ private Any() {}
+
+ public boolean matches(Object actual) {
+ return true;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("<any>");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/AnyVararg.java b/src/org/mockito/internal/matchers/AnyVararg.java
new file mode 100644
index 0000000..ce4cd02
--- /dev/null
+++ b/src/org/mockito/internal/matchers/AnyVararg.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Matcher;
+import org.mockito.ArgumentMatcher;
+
+@SuppressWarnings("unchecked")
+public class AnyVararg extends ArgumentMatcher implements VarargMatcher, Serializable {
+
+ private static final long serialVersionUID = 1700721373094731555L;
+ public static final Matcher ANY_VARARG = new AnyVararg();
+
+ public boolean matches(Object arg) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/ArrayEquals.java b/src/org/mockito/internal/matchers/ArrayEquals.java
new file mode 100644
index 0000000..c6cdf33
--- /dev/null
+++ b/src/org/mockito/internal/matchers/ArrayEquals.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+
+import org.hamcrest.Description;
+
+public class ArrayEquals extends Equals {
+
+ private static final long serialVersionUID = -7167812844261087583L;
+
+ public ArrayEquals(Object wanted) {
+ super(wanted);
+ }
+
+ public boolean matches(Object actual) {
+ Object wanted = getWanted();
+ if (wanted == null || actual == null) {
+ return super.matches(actual);
+ } else if (wanted instanceof boolean[] && actual instanceof boolean[]) {
+ return Arrays.equals((boolean[]) wanted, (boolean[]) actual);
+ } else if (wanted instanceof byte[] && actual instanceof byte[]) {
+ return Arrays.equals((byte[]) wanted, (byte[]) actual);
+ } else if (wanted instanceof char[] && actual instanceof char[]) {
+ return Arrays.equals((char[]) wanted, (char[]) actual);
+ } else if (wanted instanceof double[] && actual instanceof double[]) {
+ return Arrays.equals((double[]) wanted, (double[]) actual);
+ } else if (wanted instanceof float[] && actual instanceof float[]) {
+ return Arrays.equals((float[]) wanted, (float[]) actual);
+ } else if (wanted instanceof int[] && actual instanceof int[]) {
+ return Arrays.equals((int[]) wanted, (int[]) actual);
+ } else if (wanted instanceof long[] && actual instanceof long[]) {
+ return Arrays.equals((long[]) wanted, (long[]) actual);
+ } else if (wanted instanceof short[] && actual instanceof short[]) {
+ return Arrays.equals((short[]) wanted, (short[]) actual);
+ } else if (wanted instanceof Object[] && actual instanceof Object[]) {
+ return Arrays.equals((Object[]) wanted, (Object[]) actual);
+ }
+ return false;
+ }
+
+ public void describeTo(Description description) {
+ if (getWanted() != null && getWanted().getClass().isArray()) {
+ appendArray(createObjectArray(getWanted()), description);
+ } else {
+ super.describeTo(description);
+ }
+ }
+
+ private void appendArray(Object[] array, Description description) {
+ description.appendText("[");
+ for (int i = 0; i < array.length; i++) {
+ new Equals(array[i]).describeTo(description);
+ if (i != array.length - 1) {
+ description.appendText(", ");
+ }
+ }
+ description.appendText("]");
+ }
+
+ public static Object[] createObjectArray(Object array) {
+ if (array instanceof Object[]) {
+ return (Object[]) array;
+ }
+ Object[] result = new Object[Array.getLength(array)];
+ for (int i = 0; i < Array.getLength(array); i++) {
+ result[i] = Array.get(array, i);
+ }
+ return result;
+ }
+}
diff --git a/src/org/mockito/internal/matchers/CapturesArguments.java b/src/org/mockito/internal/matchers/CapturesArguments.java
new file mode 100644
index 0000000..5134abd
--- /dev/null
+++ b/src/org/mockito/internal/matchers/CapturesArguments.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+
+public interface CapturesArguments {
+
+ void captureFrom(Object argument);
+
+}
diff --git a/src/org/mockito/internal/matchers/CapturingMatcher.java b/src/org/mockito/internal/matchers/CapturingMatcher.java
new file mode 100644
index 0000000..3503387
--- /dev/null
+++ b/src/org/mockito/internal/matchers/CapturingMatcher.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+import org.mockito.exceptions.Reporter;
+
+@SuppressWarnings("unchecked")
+public class CapturingMatcher<T> extends ArgumentMatcher<T> implements CapturesArguments, Serializable {
+
+ private static final long serialVersionUID = 4274067078639307295L;
+ private LinkedList<Object> arguments = new LinkedList<Object>();
+
+ /* (non-Javadoc)
+ * @see org.mockito.ArgumentMatcher#matches(java.lang.Object)
+ */
+ public boolean matches(Object argument) {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.ArgumentMatcher#describeTo(org.hamcrest.Description)
+ */
+ public void describeTo(Description description) {
+ description.appendText("<Capturing argument>");
+ }
+
+ public T getLastValue() {
+ if (arguments.isEmpty()) {
+ new Reporter().noArgumentValueWasCaptured();
+ return null;
+ } else {
+ return (T) arguments.getLast();
+ }
+ }
+
+ public List<T> getAllValues() {
+ return (List) arguments;
+ }
+
+ public void captureFrom(Object argument) {
+ this.arguments.add(argument);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/CompareEqual.java b/src/org/mockito/internal/matchers/CompareEqual.java
new file mode 100644
index 0000000..643d47c
--- /dev/null
+++ b/src/org/mockito/internal/matchers/CompareEqual.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+public class CompareEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
+
+ private static final long serialVersionUID = 2998586260452920429L;
+
+ public CompareEqual(Comparable<T> value) {
+ super(value);
+ }
+
+ @Override
+ protected String getName() {
+ return "cmpEq";
+ }
+
+ @Override
+ protected boolean matchResult(int result) {
+ return result == 0;
+ }
+}
diff --git a/src/org/mockito/internal/matchers/CompareTo.java b/src/org/mockito/internal/matchers/CompareTo.java
new file mode 100644
index 0000000..428bf00
--- /dev/null
+++ b/src/org/mockito/internal/matchers/CompareTo.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+
+public abstract class CompareTo<T extends Comparable<T>> extends ArgumentMatcher<T> {
+ private final Comparable<T> wanted;
+
+ public CompareTo(Comparable<T> value) {
+ this.wanted = value;
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean matches(Object actual) {
+
+ if(!(actual instanceof Comparable)) {
+ return false;
+ }
+
+ return matchResult(((Comparable) actual).compareTo(wanted));
+ }
+
+ public void describeTo(Description description) {
+ description.appendText(getName() + "(" + wanted + ")");
+ }
+
+ protected abstract String getName();
+
+ protected abstract boolean matchResult(int result);
+}
diff --git a/src/org/mockito/internal/matchers/Contains.java b/src/org/mockito/internal/matchers/Contains.java
new file mode 100644
index 0000000..5901c08
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Contains.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+
+public class Contains extends ArgumentMatcher<String> implements Serializable {
+
+ private static final long serialVersionUID = -1909837398271763801L;
+ private final String substring;
+
+ public Contains(String substring) {
+ this.substring = substring;
+ }
+
+ public boolean matches(Object actual) {
+ return actual != null && ((String) actual).contains(substring);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("contains(\"" + substring + "\")");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/ContainsExtraTypeInformation.java b/src/org/mockito/internal/matchers/ContainsExtraTypeInformation.java
new file mode 100644
index 0000000..137a610
--- /dev/null
+++ b/src/org/mockito/internal/matchers/ContainsExtraTypeInformation.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.SelfDescribing;
+
+public interface ContainsExtraTypeInformation extends Serializable {
+ SelfDescribing withExtraTypeInfo();
+
+ boolean typeMatches(Object object);
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/EndsWith.java b/src/org/mockito/internal/matchers/EndsWith.java
new file mode 100644
index 0000000..3c92f92
--- /dev/null
+++ b/src/org/mockito/internal/matchers/EndsWith.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+
+public class EndsWith extends ArgumentMatcher<String> implements Serializable {
+
+ private static final long serialVersionUID = 8556443228350129421L;
+ private final String suffix;
+
+ public EndsWith(String suffix) {
+ this.suffix = suffix;
+ }
+
+ public boolean matches(Object actual) {
+ return actual != null && ((String) actual).endsWith(suffix);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("endsWith(\"" + suffix + "\")");
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/Equality.java b/src/org/mockito/internal/matchers/Equality.java
new file mode 100644
index 0000000..43e11fc
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Equality.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import java.lang.reflect.Array;
+
+//stolen from hamcrest because I didn't want to have more dependency than Matcher class
+public class Equality {
+
+ public static boolean areEqual(Object o1, Object o2) {
+ if (o1 == null || o2 == null) {
+ return o1 == null && o2 == null;
+ } else if (isArray(o1)) {
+ return isArray(o2) && areArraysEqual(o1, o2);
+ } else {
+ return o1.equals(o2);
+ }
+ }
+
+ static boolean areArraysEqual(Object o1, Object o2) {
+ return areArrayLengthsEqual(o1, o2)
+ && areArrayElementsEqual(o1, o2);
+ }
+
+ static boolean areArrayLengthsEqual(Object o1, Object o2) {
+ return Array.getLength(o1) == Array.getLength(o2);
+ }
+
+ static boolean areArrayElementsEqual(Object o1, Object o2) {
+ for (int i = 0; i < Array.getLength(o1); i++) {
+ if (!areEqual(Array.get(o1, i), Array.get(o2, i))) return false;
+ }
+ return true;
+ }
+
+ static boolean isArray(Object o) {
+ return o.getClass().isArray();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/Equals.java b/src/org/mockito/internal/matchers/Equals.java
new file mode 100644
index 0000000..4631de6
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Equals.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import org.hamcrest.Description;
+import org.hamcrest.SelfDescribing;
+import org.mockito.ArgumentMatcher;
+
+import java.io.Serializable;
+
+public class Equals extends ArgumentMatcher<Object> implements ContainsExtraTypeInformation, Serializable {
+
+ private static final long serialVersionUID = -3395637450058086891L;
+ private final Object wanted;
+
+ public Equals(Object wanted) {
+ this.wanted = wanted;
+ }
+
+ public boolean matches(Object actual) {
+ return Equality.areEqual(this.wanted, actual);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText(describe(wanted));
+ }
+
+ public String describe(Object object) {
+ String text = quoting();
+ text+="" + object;
+ text+= quoting();
+ return text;
+ }
+
+ private String quoting() {
+ if (wanted instanceof String) {
+ return "\"";
+ } else if (wanted instanceof Character) {
+ return "'";
+ } else {
+ return "";
+ }
+ }
+
+ protected final Object getWanted() {
+ return wanted;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || !this.getClass().equals(o.getClass())) {
+ return false;
+ }
+ Equals other = (Equals) o;
+ return this.wanted == null && other.wanted == null || this.wanted != null && this.wanted.equals(other.wanted);
+ }
+
+ @Override
+ public int hashCode() {
+ return 1;
+ }
+
+ public SelfDescribing withExtraTypeInfo() {
+ return new SelfDescribing() {
+ public void describeTo(Description description) {
+ description.appendText(describe("("+ wanted.getClass().getSimpleName() +") " + wanted));
+ }};
+ }
+
+ public boolean typeMatches(Object object) {
+ return wanted != null && object != null && object.getClass() == wanted.getClass();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/EqualsWithDelta.java b/src/org/mockito/internal/matchers/EqualsWithDelta.java
new file mode 100644
index 0000000..6e35038
--- /dev/null
+++ b/src/org/mockito/internal/matchers/EqualsWithDelta.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+import java.io.Serializable;
+
+
+public class EqualsWithDelta extends ArgumentMatcher<Number> implements Serializable {
+ private static final long serialVersionUID = 5066980489920383664L;
+
+ private final Number wanted;
+
+ private final Number delta;
+
+ public EqualsWithDelta(Number value, Number delta) {
+ this.wanted = value;
+ this.delta = delta;
+ }
+
+ public boolean matches(Object actual) {
+ Number actualNumber = (Number) actual;
+ if (wanted == null ^ actual == null) {
+ return false;
+ }
+
+ if (wanted == null && actual == null) {
+ return true;
+ }
+
+ return wanted.doubleValue() - delta.doubleValue() <= actualNumber.doubleValue()
+ && actualNumber.doubleValue() <= wanted.doubleValue()
+ + delta.doubleValue();
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("eq(" + wanted + ", " + delta + ")");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/Find.java b/src/org/mockito/internal/matchers/Find.java
new file mode 100644
index 0000000..9c07796
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Find.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+import java.util.regex.Pattern;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+public class Find extends ArgumentMatcher<String> implements Serializable {
+
+ private static final long serialVersionUID = 8895781429480404872L;
+ private final String regex;
+
+ public Find(String regex) {
+ this.regex = regex;
+ }
+
+ public boolean matches(Object actual) {
+ return actual != null && Pattern.compile(regex).matcher((String) actual).find();
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("find(\"" + regex.replaceAll("\\\\", "\\\\\\\\") + "\")");
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/GreaterOrEqual.java b/src/org/mockito/internal/matchers/GreaterOrEqual.java
new file mode 100644
index 0000000..a67cb1a
--- /dev/null
+++ b/src/org/mockito/internal/matchers/GreaterOrEqual.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+public class GreaterOrEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
+
+ private static final long serialVersionUID = 87695769061286092L;
+
+ public GreaterOrEqual(Comparable<T> value) {
+ super(value);
+ }
+
+ @Override
+ protected String getName() {
+ return "geq";
+ }
+
+ @Override
+ protected boolean matchResult(int result) {
+ return result >= 0;
+ }
+}
diff --git a/src/org/mockito/internal/matchers/GreaterThan.java b/src/org/mockito/internal/matchers/GreaterThan.java
new file mode 100644
index 0000000..9130acf
--- /dev/null
+++ b/src/org/mockito/internal/matchers/GreaterThan.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+public class GreaterThan<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
+
+ private static final long serialVersionUID = 7446529803235604408L;
+
+ public GreaterThan(Comparable<T> value) {
+ super(value);
+ }
+
+ @Override
+ protected String getName() {
+ return "gt";
+ }
+
+ @Override
+ protected boolean matchResult(int result) {
+ return result > 0;
+ }
+}
diff --git a/src/org/mockito/internal/matchers/InstanceOf.java b/src/org/mockito/internal/matchers/InstanceOf.java
new file mode 100644
index 0000000..f976d8f
--- /dev/null
+++ b/src/org/mockito/internal/matchers/InstanceOf.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+
+public class InstanceOf extends ArgumentMatcher<Object> implements Serializable {
+
+ private static final long serialVersionUID = 517358915876138366L;
+ private final Class<?> clazz;
+
+ public InstanceOf(Class<?> clazz) {
+ this.clazz = clazz;
+ }
+
+ public boolean matches(Object actual) {
+ return (actual != null) && clazz.isAssignableFrom(actual.getClass());
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("isA(" + clazz.getName() + ")");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/LessOrEqual.java b/src/org/mockito/internal/matchers/LessOrEqual.java
new file mode 100644
index 0000000..82a09c1
--- /dev/null
+++ b/src/org/mockito/internal/matchers/LessOrEqual.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+public class LessOrEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
+
+ private static final long serialVersionUID = -6648773374429103565L;
+
+ public LessOrEqual(Comparable<T> value) {
+ super(value);
+ }
+
+ @Override
+ protected String getName() {
+ return "leq";
+ }
+
+ @Override
+ protected boolean matchResult(int result) {
+ return result <= 0;
+ }
+}
diff --git a/src/org/mockito/internal/matchers/LessThan.java b/src/org/mockito/internal/matchers/LessThan.java
new file mode 100644
index 0000000..19d5a80
--- /dev/null
+++ b/src/org/mockito/internal/matchers/LessThan.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+public class LessThan<T extends Comparable<T>> extends CompareTo<T> implements Serializable {
+
+ private static final long serialVersionUID = -133860804462310942L;
+
+ public LessThan(Comparable<T> value) {
+ super(value);
+ }
+
+ @Override
+ protected String getName() {
+ return "lt";
+ }
+
+ @Override
+ protected boolean matchResult(int result) {
+ return result < 0;
+ }
+}
diff --git a/src/org/mockito/internal/matchers/LocalizedMatcher.java b/src/org/mockito/internal/matchers/LocalizedMatcher.java
new file mode 100644
index 0000000..4021ce0
--- /dev/null
+++ b/src/org/mockito/internal/matchers/LocalizedMatcher.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.*;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.invocation.Location;
+
+@SuppressWarnings("unchecked")
+public class LocalizedMatcher implements Matcher, ContainsExtraTypeInformation, CapturesArguments, MatcherDecorator, Serializable {
+
+ private static final long serialVersionUID = 6748641229659825725L;
+ private final Matcher actualMatcher;
+ private Location location;
+
+ public LocalizedMatcher(Matcher actualMatcher) {
+ this.actualMatcher = actualMatcher;
+ this.location = new LocationImpl();
+ }
+
+ public void _dont_implement_Matcher___instead_extend_BaseMatcher_() {
+ // yeah right
+ }
+
+ public boolean matches(Object item) {
+ return actualMatcher.matches(item);
+ }
+
+ public void describeTo(Description description) {
+ actualMatcher.describeTo(description);
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ @Override
+ public String toString() {
+ return "Localized: " + this.actualMatcher;
+ }
+
+ public SelfDescribing withExtraTypeInfo() {
+ if (actualMatcher instanceof ContainsExtraTypeInformation) {
+ return ((ContainsExtraTypeInformation) actualMatcher).withExtraTypeInfo();
+ } else {
+ return this;
+ }
+ }
+
+ public boolean typeMatches(Object object) {
+ return actualMatcher instanceof ContainsExtraTypeInformation
+ && ((ContainsExtraTypeInformation) actualMatcher).typeMatches(object);
+ }
+
+ public void captureFrom(Object argument) {
+ if (actualMatcher instanceof CapturesArguments) {
+ ((CapturesArguments) actualMatcher).captureFrom(argument);
+ }
+ }
+
+ //TODO: refactor other 'delegated interfaces' to use the MatcherDecorator feature
+ public Matcher getActualMatcher() {
+ return actualMatcher;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/MatcherDecorator.java b/src/org/mockito/internal/matchers/MatcherDecorator.java
new file mode 100644
index 0000000..aa01160
--- /dev/null
+++ b/src/org/mockito/internal/matchers/MatcherDecorator.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Matcher;
+
+@SuppressWarnings("unchecked")
+public interface MatcherDecorator extends Serializable {
+ Matcher getActualMatcher();
+}
diff --git a/src/org/mockito/internal/matchers/MatchersPrinter.java b/src/org/mockito/internal/matchers/MatchersPrinter.java
new file mode 100644
index 0000000..f0505bf
--- /dev/null
+++ b/src/org/mockito/internal/matchers/MatchersPrinter.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.SelfDescribing;
+import org.hamcrest.StringDescription;
+import org.mockito.internal.reporting.PrintSettings;
+
+@SuppressWarnings("unchecked")
+public class MatchersPrinter {
+
+ public String getArgumentsLine(List<Matcher> matchers, PrintSettings printSettings) {
+ Description result = new StringDescription();
+ result.appendList("(", ", ", ");", applyPrintSettings(matchers, printSettings));
+ return result.toString();
+ }
+
+ public String getArgumentsBlock(List<Matcher> matchers, PrintSettings printSettings) {
+ Description result = new StringDescription();
+ result.appendList("(\n ", ",\n ", "\n);", applyPrintSettings(matchers, printSettings));
+ return result.toString();
+ }
+
+ private List<SelfDescribing> applyPrintSettings(List<Matcher> matchers, PrintSettings printSettings) {
+ List<SelfDescribing> withPrintSettings = new LinkedList<SelfDescribing>();
+ int i = 0;
+ for (final Matcher matcher : matchers) {
+ if (matcher instanceof ContainsExtraTypeInformation && printSettings.extraTypeInfoFor(i)) {
+ withPrintSettings.add(((ContainsExtraTypeInformation) matcher).withExtraTypeInfo());
+ } else {
+ withPrintSettings.add(matcher);
+ }
+ i++;
+ }
+ return withPrintSettings;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/Matches.java b/src/org/mockito/internal/matchers/Matches.java
new file mode 100644
index 0000000..f7dd560
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Matches.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+
+public class Matches extends ArgumentMatcher<Object> implements Serializable {
+
+ private static final long serialVersionUID = 8787704593379472029L;
+ private final String regex;
+
+ public Matches(String regex) {
+ this.regex = regex;
+ }
+
+ public boolean matches(Object actual) {
+ return (actual instanceof String) && ((String) actual).matches(regex);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("matches(\"" + regex.replaceAll("\\\\", "\\\\\\\\")
+ + "\")");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/Not.java b/src/org/mockito/internal/matchers/Not.java
new file mode 100644
index 0000000..70d581a
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Not.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.mockito.ArgumentMatcher;
+
+@SuppressWarnings("unchecked")
+public class Not extends ArgumentMatcher implements Serializable {
+
+ private static final long serialVersionUID = 4627373642333593264L;
+ private final Matcher first;
+
+ public Not(Matcher first) {
+ this.first = first;
+ }
+
+ public boolean matches(Object actual) {
+ return !first.matches(actual);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("not(");
+ first.describeTo(description);
+ description.appendText(")");
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/NotNull.java b/src/org/mockito/internal/matchers/NotNull.java
new file mode 100644
index 0000000..9453ea5
--- /dev/null
+++ b/src/org/mockito/internal/matchers/NotNull.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+
+public class NotNull extends ArgumentMatcher<Object> implements Serializable {
+
+ private static final long serialVersionUID = 7278261081285153228L;
+ public static final NotNull NOT_NULL = new NotNull();
+
+ private NotNull() {
+
+ }
+
+ public boolean matches(Object actual) {
+ return actual != null;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("notNull()");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/Null.java b/src/org/mockito/internal/matchers/Null.java
new file mode 100644
index 0000000..31d95db
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Null.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+
+public class Null extends ArgumentMatcher<Object> implements Serializable {
+
+ private static final long serialVersionUID = 2823082637424390314L;
+ public static final Null NULL = new Null();
+
+ private Null() {
+ }
+
+ public boolean matches(Object actual) {
+ return actual == null;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("isNull()");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/Or.java b/src/org/mockito/internal/matchers/Or.java
new file mode 100644
index 0000000..5b739b7
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Or.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.mockito.ArgumentMatcher;
+
+@SuppressWarnings("unchecked")
+public class Or extends ArgumentMatcher implements Serializable {
+
+ private static final long serialVersionUID = 5888739035212283087L;
+ private final List<Matcher> matchers;
+
+ public Or(List<Matcher> matchers) {
+ this.matchers = matchers;
+ }
+
+ public boolean matches(Object actual) {
+ for (Matcher matcher : matchers) {
+ if (matcher.matches(actual)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("or(");
+ for (Iterator<Matcher> it = matchers.iterator(); it.hasNext();) {
+ it.next().describeTo(description);
+ if (it.hasNext()) {
+ description.appendText(", ");
+ }
+ }
+ description.appendText(")");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/Same.java b/src/org/mockito/internal/matchers/Same.java
new file mode 100644
index 0000000..7ab6da3
--- /dev/null
+++ b/src/org/mockito/internal/matchers/Same.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+import java.io.Serializable;
+
+
+public class Same extends ArgumentMatcher<Object> implements Serializable {
+
+ private static final long serialVersionUID = -1226959355938572597L;
+ private final Object wanted;
+
+ public Same(Object wanted) {
+ this.wanted = wanted;
+ }
+
+ public boolean matches(Object actual) {
+ return wanted == actual;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("same(");
+ appendQuoting(description);
+ description.appendText("" + wanted);
+ appendQuoting(description);
+ description.appendText(")");
+ }
+
+ private void appendQuoting(Description description) {
+ if (wanted instanceof String) {
+ description.appendText("\"");
+ } else if (wanted instanceof Character) {
+ description.appendText("'");
+ }
+ }
+}
diff --git a/src/org/mockito/internal/matchers/StartsWith.java b/src/org/mockito/internal/matchers/StartsWith.java
new file mode 100644
index 0000000..3557ff0
--- /dev/null
+++ b/src/org/mockito/internal/matchers/StartsWith.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+
+public class StartsWith extends ArgumentMatcher<String> implements Serializable {
+
+ private static final long serialVersionUID = -5978092285707998431L;
+ private final String prefix;
+
+ public StartsWith(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public boolean matches(Object actual) {
+ return actual != null && ((String) actual).startsWith(prefix);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("startsWith(\"" + prefix + "\")");
+ }
+}
diff --git a/src/org/mockito/internal/matchers/VarargCapturingMatcher.java b/src/org/mockito/internal/matchers/VarargCapturingMatcher.java
new file mode 100644
index 0000000..103378b
--- /dev/null
+++ b/src/org/mockito/internal/matchers/VarargCapturingMatcher.java
@@ -0,0 +1,59 @@
+package org.mockito.internal.matchers;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+import org.mockito.exceptions.Reporter;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+
+@SuppressWarnings("unchecked")
+public class VarargCapturingMatcher<T> extends ArgumentMatcher<T> implements CapturesArguments, VarargMatcher, Serializable {
+ private static final long serialVersionUID = 4057053345838026645L;
+ private LinkedList<List<T>> arguments = new LinkedList<List<T>>();
+
+ public boolean matches(Object argument) {
+ return true;
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("<Capturing variable argument>");
+ }
+
+ public List<T> getLastVarargs() {
+ if (arguments.isEmpty()) {
+ new Reporter().noArgumentValueWasCaptured();
+ return null;
+ } else {
+ return arguments.getLast();
+ }
+ }
+
+ public List<List<T>> getAllVarargs() {
+ return arguments;
+ }
+
+ public void captureFrom(Object varArgArray) {
+ List<T> vararg = unpackAsList(varArgArray);
+ this.arguments.add(vararg);
+ }
+
+ private List<T> unpackAsList(Object varArgArray) {
+ if (varArgArray instanceof Object[]) {
+ return Arrays.asList((T[]) varArgArray);
+ } else if (varArgArray.getClass().isArray()) {
+ Object[] primitiveArray = new Object[Array.getLength(varArgArray)];
+ for (int i = 0; i < primitiveArray.length; i++) {
+ primitiveArray[i] = Array.get(varArgArray, i);
+ }
+ return Arrays.asList((T[]) primitiveArray);
+ } else {
+ return Collections.singletonList((T) varArgArray);
+ }
+ }
+}
diff --git a/src/org/mockito/internal/matchers/VarargMatcher.java b/src/org/mockito/internal/matchers/VarargMatcher.java
new file mode 100644
index 0000000..5e04dcc
--- /dev/null
+++ b/src/org/mockito/internal/matchers/VarargMatcher.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.matchers;
+
+import java.io.Serializable;
+
+public interface VarargMatcher extends Serializable {
+}
diff --git a/src/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java b/src/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java
new file mode 100644
index 0000000..97ea911
--- /dev/null
+++ b/src/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java
@@ -0,0 +1,815 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+//NON-STANDARD LICENCE HEADER HERE - THAT'S OK
+//Class comes from Apache Commons Lang, added some tiny changes
+package org.mockito.internal.matchers.apachecommons;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>Assists in implementing {@link Object#equals(Object)} methods.</p>
+ *
+ * <p> This class provides methods to build a good equals method for any
+ * class. It follows rules laid out in
+ * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
+ * , by Joshua Bloch. In particular the rule for comparing <code>doubles</code>,
+ * <code>floats</code>, and arrays can be tricky. Also, making sure that
+ * <code>equals()</code> and <code>hashCode()</code> are consistent can be
+ * difficult.</p>
+ *
+ * <p>Two Objects that compare as equals must generate the same hash code,
+ * but two Objects with the same hash code do not have to be equal.</p>
+ *
+ * <p>All relevant fields should be included in the calculation of equals.
+ * Derived fields may be ignored. In particular, any field used in
+ * generating a hash code must be used in the equals method, and vice
+ * versa.</p>
+ *
+ * <p>Typical use for the code is as follows:</p>
+ * <pre class="code"><code class="java">
+ * public boolean equals(Object obj) {
+ * if (obj == null) { return false; }
+ * if (obj == this) { return true; }
+ * if (obj.getClass() != getClass()) {
+ * return false;
+ * }
+ * MyClass rhs = (MyClass) obj;
+ * return new EqualsBuilder()
+ * .appendSuper(super.equals(obj))
+ * .append(field1, rhs.field1)
+ * .append(field2, rhs.field2)
+ * .append(field3, rhs.field3)
+ * .isEquals();
+ * }
+ * </code></pre>
+ *
+ * <p> Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * <code>reflectionEquals</code>, uses <code>AccessibleObject.setAccessible</code> to
+ * change the visibility of the fields. This will fail under a security
+ * manager, unless the appropriate permissions are set up correctly. It is
+ * also slower than testing explicitly.</p>
+ *
+ * <p> A typical invocation for this method would look like:</p>
+ * <pre class="code"><code class="java">
+ * public boolean equals(Object obj) {
+ * return EqualsBuilder.reflectionEquals(this, obj);
+ * }
+ * </code></pre>
+ *
+ * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @author Arun Mammen Thomas
+ * @since 1.0
+ * @version $Id: EqualsBuilder.java 611543 2008-01-13 07:00:22Z bayard $
+ */
+@SuppressWarnings("unchecked")
+class EqualsBuilder {
+
+ /**
+ * If the fields tested are equals.
+ * The default value is <code>true</code>.
+ */
+ private boolean isEquals = true;
+
+ /**
+ * <p>Constructor for EqualsBuilder.</p>
+ *
+ * <p>Starts off assuming that equals is <code>true</code>.</p>
+ * @see Object#equals(Object)
+ */
+ public EqualsBuilder() {
+ // do nothing for now.
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>This method uses reflection to determine if the two <code>Object</code>s
+ * are equal.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>Transient members will be not be tested, as they are likely derived
+ * fields, and not part of the value of the Object.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * @param lhs <code>this</code> object
+ * @param rhs the other object
+ * @return <code>true</code> if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs) {
+ return reflectionEquals(lhs, rhs, false, null, null);
+ }
+
+ /**
+ * <p>This method uses reflection to determine if the two <code>Object</code>s
+ * are equal.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>Transient members will be not be tested, as they are likely derived
+ * fields, and not part of the value of the Object.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * @param lhs <code>this</code> object
+ * @param rhs the other object
+ * @param excludeFields array of field names to exclude from testing
+ * @return <code>true</code> if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, String[] excludeFields) {
+ return reflectionEquals(lhs, rhs, false, null, excludeFields);
+ }
+
+ /**
+ * <p>This method uses reflection to determine if the two <code>Object</code>s
+ * are equal.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>If the TestTransients parameter is set to <code>true</code>, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be tested. Superclass fields will be included.</p>
+ *
+ * @param lhs <code>this</code> object
+ * @param rhs the other object
+ * @param testTransients whether to include transient fields
+ * @return <code>true</code> if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients) {
+ return reflectionEquals(lhs, rhs, testTransients, null, null);
+ }
+
+ /**
+ * <p>This method uses reflection to determine if the two <code>Object</code>s
+ * are equal.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>If the testTransients parameter is set to <code>true</code>, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be included. Superclass fields will be appended
+ * up to and including the specified superclass. A null superclass is treated
+ * as java.lang.Object.</p>
+ *
+ * @param lhs <code>this</code> object
+ * @param rhs the other object
+ * @param testTransients whether to include transient fields
+ * @param reflectUpToClass the superclass to reflect up to (inclusive),
+ * may be <code>null</code>
+ * @return <code>true</code> if the two Objects have tested equals.
+ * @since 2.0
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) {
+ return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, null);
+ }
+
+ /**
+ * <p>This method uses reflection to determine if the two <code>Object</code>s
+ * are equal.</p>
+ *
+ * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manager, if the permissions are not set up correctly. It is also
+ * not as efficient as testing explicitly.</p>
+ *
+ * <p>If the testTransients parameter is set to <code>true</code>, transient
+ * members will be tested, otherwise they are ignored, as they are likely
+ * derived fields, and not part of the value of the <code>Object</code>.</p>
+ *
+ * <p>Static fields will not be included. Superclass fields will be appended
+ * up to and including the specified superclass. A null superclass is treated
+ * as java.lang.Object.</p>
+ *
+ * @param lhs <code>this</code> object
+ * @param rhs the other object
+ * @param testTransients whether to include transient fields
+ * @param reflectUpToClass the superclass to reflect up to (inclusive),
+ * may be <code>null</code>
+ * @param excludeFields array of field names to exclude from testing
+ * @return <code>true</code> if the two Objects have tested equals.
+ * @since 2.0
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass,
+ String[] excludeFields) {
+ if (lhs == rhs) {
+ return true;
+ }
+ if (lhs == null || rhs == null) {
+ return false;
+ }
+ // Find the leaf class since there may be transients in the leaf
+ // class or in classes between the leaf and root.
+ // If we are not testing transients or a subclass has no ivars,
+ // then a subclass can test equals to a superclass.
+ Class lhsClass = lhs.getClass();
+ Class rhsClass = rhs.getClass();
+ Class testClass;
+ if (lhsClass.isInstance(rhs)) {
+ testClass = lhsClass;
+ if (!rhsClass.isInstance(lhs)) {
+ // rhsClass is a subclass of lhsClass
+ testClass = rhsClass;
+ }
+ } else if (rhsClass.isInstance(lhs)) {
+ testClass = rhsClass;
+ if (!lhsClass.isInstance(rhs)) {
+ // lhsClass is a subclass of rhsClass
+ testClass = lhsClass;
+ }
+ } else {
+ // The two classes are not related.
+ return false;
+ }
+ EqualsBuilder equalsBuilder = new EqualsBuilder();
+ try {
+ reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields);
+ while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
+ testClass = testClass.getSuperclass();
+ reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields);
+ }
+ } catch (IllegalArgumentException e) {
+ // In this case, we tried to test a subclass vs. a superclass and
+ // the subclass has ivars or the ivars are transient and
+ // we are testing transients.
+ // If a subclass has ivars that we are trying to test them, we get an
+ // exception and we know that the objects are not equal.
+ return false;
+ }
+ return equalsBuilder.isEquals();
+ }
+
+ /**
+ * <p>Appends the fields and values defined by the given object of the
+ * given Class.</p>
+ *
+ * @param lhs the left hand object
+ * @param rhs the right hand object
+ * @param clazz the class to append details of
+ * @param builder the builder to append to
+ * @param useTransients whether to test transient fields
+ * @param excludeFields array of field names to exclude from testing
+ */
+ private static void reflectionAppend(
+ Object lhs,
+ Object rhs,
+ Class clazz,
+ EqualsBuilder builder,
+ boolean useTransients,
+ String[] excludeFields) {
+ Field[] fields = clazz.getDeclaredFields();
+ List excludedFieldList = excludeFields != null ? Arrays.asList(excludeFields) : Collections.EMPTY_LIST;
+ AccessibleObject.setAccessible(fields, true);
+ for (int i = 0; i < fields.length && builder.isEquals; i++) {
+ Field f = fields[i];
+ if (!excludedFieldList.contains(f.getName())
+ && (f.getName().indexOf('$') == -1)
+ && (useTransients || !Modifier.isTransient(f.getModifiers()))
+ && (!Modifier.isStatic(f.getModifiers()))) {
+ try {
+ builder.append(f.get(lhs), f.get(rhs));
+ } catch (IllegalAccessException e) {
+ //this can't happen. Would get a Security exception instead
+ //throw a runtime exception in case the impossible happens.
+ throw new InternalError("Unexpected IllegalAccessException");
+ }
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>Adds the result of <code>super.equals()</code> to this builder.</p>
+ *
+ * @param superEquals the result of calling <code>super.equals()</code>
+ * @return EqualsBuilder - used to chain calls.
+ * @since 2.0
+ */
+ public EqualsBuilder appendSuper(boolean superEquals) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = superEquals;
+ return this;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * <p>Test if two <code>Object</code>s are equal using their
+ * <code>equals</code> method.</p>
+ *
+ * @param lhs the left hand object
+ * @param rhs the right hand object
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(Object lhs, Object rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ Class lhsClass = lhs.getClass();
+ if (!lhsClass.isArray()) {
+ if (lhs instanceof java.math.BigDecimal && rhs instanceof java.math.BigDecimal) {
+ isEquals = (((java.math.BigDecimal) lhs).compareTo((java.math.BigDecimal) rhs) == 0);
+ } else {
+ // The simple case, not an array, just test the element
+ isEquals = lhs.equals(rhs);
+ }
+ } else if (lhs.getClass() != rhs.getClass()) {
+ // Here when we compare different dimensions, for example: a boolean[][] to a boolean[]
+ this.setEquals(false);
+
+ // 'Switch' on type of array, to dispatch to the correct handler
+ // This handles multi dimensional arrays of the same depth
+ } else if (lhs instanceof long[]) {
+ append((long[]) lhs, (long[]) rhs);
+ } else if (lhs instanceof int[]) {
+ append((int[]) lhs, (int[]) rhs);
+ } else if (lhs instanceof short[]) {
+ append((short[]) lhs, (short[]) rhs);
+ } else if (lhs instanceof char[]) {
+ append((char[]) lhs, (char[]) rhs);
+ } else if (lhs instanceof byte[]) {
+ append((byte[]) lhs, (byte[]) rhs);
+ } else if (lhs instanceof double[]) {
+ append((double[]) lhs, (double[]) rhs);
+ } else if (lhs instanceof float[]) {
+ append((float[]) lhs, (float[]) rhs);
+ } else if (lhs instanceof boolean[]) {
+ append((boolean[]) lhs, (boolean[]) rhs);
+ } else {
+ // Not an array of primitives
+ append((Object[]) lhs, (Object[]) rhs);
+ }
+ return this;
+ }
+
+ /**
+ * <p>
+ * Test if two <code>long</code> s are equal.
+ * </p>
+ *
+ * @param lhs
+ * the left hand <code>long</code>
+ * @param rhs
+ * the right hand <code>long</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(long lhs, long rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>int</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>int</code>
+ * @param rhs the right hand <code>int</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(int lhs, int rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>short</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>short</code>
+ * @param rhs the right hand <code>short</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(short lhs, short rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>char</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>char</code>
+ * @param rhs the right hand <code>char</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(char lhs, char rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>byte</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>byte</code>
+ * @param rhs the right hand <code>byte</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(byte lhs, byte rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Test if two <code>double</code>s are equal by testing that the
+ * pattern of bits returned by <code>doubleToLong</code> are equal.</p>
+ *
+ * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
+ *
+ * <p>It is compatible with the hash code generated by
+ * <code>HashCodeBuilder</code>.</p>
+ *
+ * @param lhs the left hand <code>double</code>
+ * @param rhs the right hand <code>double</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(double lhs, double rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs));
+ }
+
+ /**
+ * <p>Test if two <code>float</code>s are equal byt testing that the
+ * pattern of bits returned by doubleToLong are equal.</p>
+ *
+ * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
+ *
+ * <p>It is compatible with the hash code generated by
+ * <code>HashCodeBuilder</code>.</p>
+ *
+ * @param lhs the left hand <code>float</code>
+ * @param rhs the right hand <code>float</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(float lhs, float rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs));
+ }
+
+ /**
+ * <p>Test if two <code>booleans</code>s are equal.</p>
+ *
+ * @param lhs the left hand <code>boolean</code>
+ * @param rhs the right hand <code>boolean</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(boolean lhs, boolean rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * <p>Performs a deep comparison of two <code>Object</code> arrays.</p>
+ *
+ * <p>This also will be called for the top level of
+ * multi-dimensional, ragged, and multi-typed arrays.</p>
+ *
+ * @param lhs the left hand <code>Object[]</code>
+ * @param rhs the right hand <code>Object[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(Object[] lhs, Object[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>long</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(long, long)} is used.</p>
+ *
+ * @param lhs the left hand <code>long[]</code>
+ * @param rhs the right hand <code>long[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(long[] lhs, long[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>int</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(int, int)} is used.</p>
+ *
+ * @param lhs the left hand <code>int[]</code>
+ * @param rhs the right hand <code>int[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(int[] lhs, int[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>short</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(short, short)} is used.</p>
+ *
+ * @param lhs the left hand <code>short[]</code>
+ * @param rhs the right hand <code>short[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(short[] lhs, short[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>char</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(char, char)} is used.</p>
+ *
+ * @param lhs the left hand <code>char[]</code>
+ * @param rhs the right hand <code>char[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(char[] lhs, char[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>byte</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(byte, byte)} is used.</p>
+ *
+ * @param lhs the left hand <code>byte[]</code>
+ * @param rhs the right hand <code>byte[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(byte[] lhs, byte[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>double</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(double, double)} is used.</p>
+ *
+ * @param lhs the left hand <code>double[]</code>
+ * @param rhs the right hand <code>double[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(double[] lhs, double[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>float</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(float, float)} is used.</p>
+ *
+ * @param lhs the left hand <code>float[]</code>
+ * @param rhs the right hand <code>float[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(float[] lhs, float[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Deep comparison of array of <code>boolean</code>. Length and all
+ * values are compared.</p>
+ *
+ * <p>The method {@link #append(boolean, boolean)} is used.</p>
+ *
+ * @param lhs the left hand <code>boolean[]</code>
+ * @param rhs the right hand <code>boolean[]</code>
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(boolean[] lhs, boolean[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ this.setEquals(false);
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ this.setEquals(false);
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the fields that have been checked
+ * are all equal.</p>
+ *
+ * @return boolean
+ */
+ public boolean isEquals() {
+ return this.isEquals;
+ }
+
+ /**
+ * Sets the <code>isEquals</code> value.
+ *
+ * @param isEquals The value to set.
+ * @since 2.1
+ */
+ protected void setEquals(boolean isEquals) {
+ this.isEquals = isEquals;
+ }
+}
diff --git a/src/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java b/src/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java
new file mode 100644
index 0000000..9568cd6
--- /dev/null
+++ b/src/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.matchers.apachecommons;
+
+import java.io.Serializable;
+
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
+public class ReflectionEquals extends ArgumentMatcher<Object> implements Serializable {
+ private static final long serialVersionUID = 2022780425116330014L;
+ private final Object wanted;
+ private final String[] excludeFields;
+
+ public ReflectionEquals(Object wanted, String... excludeFields) {
+ this.wanted = wanted;
+ this.excludeFields = excludeFields;
+ }
+
+ public boolean matches(Object actual) {
+ return EqualsBuilder.reflectionEquals(wanted, actual, excludeFields);
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("refEq(" + wanted + ")");
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/apachecommons/commons-lang-license.txt b/src/org/mockito/internal/matchers/apachecommons/commons-lang-license.txt
new file mode 100644
index 0000000..753842b
--- /dev/null
+++ b/src/org/mockito/internal/matchers/apachecommons/commons-lang-license.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/apachecommons/package.html b/src/org/mockito/internal/matchers/apachecommons/package.html
new file mode 100644
index 0000000..bbb72c8
--- /dev/null
+++ b/src/org/mockito/internal/matchers/apachecommons/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Argument matchers that use Apache Commons Lang reflection-equality.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/matchers/package.html b/src/org/mockito/internal/matchers/package.html
new file mode 100644
index 0000000..26b6f88
--- /dev/null
+++ b/src/org/mockito/internal/matchers/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Argument matchers for verification and stubbing.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/package.html b/src/org/mockito/internal/package.html
new file mode 100644
index 0000000..bd8f199
--- /dev/null
+++ b/src/org/mockito/internal/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Internal classes, not to be used by clients.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/ArgumentMatcherStorage.java b/src/org/mockito/internal/progress/ArgumentMatcherStorage.java
new file mode 100644
index 0000000..3beee43
--- /dev/null
+++ b/src/org/mockito/internal/progress/ArgumentMatcherStorage.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.progress;
+
+import org.hamcrest.Matcher;
+import org.mockito.internal.matchers.LocalizedMatcher;
+
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public interface ArgumentMatcherStorage {
+
+ HandyReturnValues reportMatcher(Matcher matcher);
+
+ List<LocalizedMatcher> pullLocalizedMatchers();
+
+ HandyReturnValues reportAnd();
+
+ HandyReturnValues reportNot();
+
+ HandyReturnValues reportOr();
+
+ void validateState();
+
+ void reset();
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java b/src/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java
new file mode 100644
index 0000000..6ab59d6
--- /dev/null
+++ b/src/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.progress;
+
+import org.hamcrest.Matcher;
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.matchers.And;
+import org.mockito.internal.matchers.LocalizedMatcher;
+import org.mockito.internal.matchers.Not;
+import org.mockito.internal.matchers.Or;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+
+@SuppressWarnings("unchecked")
+public class ArgumentMatcherStorageImpl implements ArgumentMatcherStorage {
+
+ public static final int TWO_SUB_MATCHERS = 2;
+ public static final int ONE_SUB_MATCHER = 1;
+ private Stack<LocalizedMatcher> matcherStack = new Stack<LocalizedMatcher>();
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.progress.ArgumentMatcherStorage#reportMatcher(org.hamcrest.Matcher)
+ */
+ public HandyReturnValues reportMatcher(Matcher matcher) {
+ matcherStack.push(new LocalizedMatcher(matcher));
+ return new HandyReturnValues();
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.progress.ArgumentMatcherStorage#pullLocalizedMatchers()
+ */
+ public List<LocalizedMatcher> pullLocalizedMatchers() {
+ if (matcherStack.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ List<LocalizedMatcher> matchers = new ArrayList<LocalizedMatcher>(matcherStack);
+ matcherStack.clear();
+ return (List) matchers;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.progress.ArgumentMatcherStorage#reportAnd()
+ */
+ public HandyReturnValues reportAnd() {
+ assertStateFor("And(?)", TWO_SUB_MATCHERS);
+ And and = new And(popLastArgumentMatchers(TWO_SUB_MATCHERS));
+ matcherStack.push(new LocalizedMatcher(and));
+ return new HandyReturnValues();
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.progress.ArgumentMatcherStorage#reportOr()
+ */
+ public HandyReturnValues reportOr() {
+ assertStateFor("Or(?)", TWO_SUB_MATCHERS);
+ Or or = new Or(popLastArgumentMatchers(TWO_SUB_MATCHERS));
+ matcherStack.push(new LocalizedMatcher(or));
+ return new HandyReturnValues();
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.progress.ArgumentMatcherStorage#reportNot()
+ */
+ public HandyReturnValues reportNot() {
+ assertStateFor("Not(?)", ONE_SUB_MATCHER);
+ Not not = new Not(popLastArgumentMatchers(ONE_SUB_MATCHER).get(0));
+ matcherStack.push(new LocalizedMatcher(not));
+ return new HandyReturnValues();
+ }
+
+ private void assertStateFor(String additionalMatcherName, int subMatchersCount) {
+ assertMatchersFoundFor(additionalMatcherName);
+ assertIncorrectUseOfAdditionalMatchers(additionalMatcherName, subMatchersCount);
+ }
+
+ private List<Matcher> popLastArgumentMatchers(int count) {
+ List<Matcher> result = new LinkedList<Matcher>();
+ result.addAll(matcherStack.subList(matcherStack.size() - count, matcherStack.size()));
+ for (int i = 0; i < count; i++) {
+ matcherStack.pop();
+ }
+ return result;
+ }
+
+ private void assertMatchersFoundFor(String additionalMatcherName) {
+ if (matcherStack.isEmpty()) {
+ matcherStack.clear();
+ new Reporter().reportNoSubMatchersFound(additionalMatcherName);
+ }
+ }
+
+ private void assertIncorrectUseOfAdditionalMatchers(String additionalMatcherName, int count) {
+ if(matcherStack.size() < count) {
+ ArrayList<LocalizedMatcher> lastMatchers = new ArrayList<LocalizedMatcher>(matcherStack);
+ matcherStack.clear();
+ new Reporter().incorrectUseOfAdditionalMatchers(additionalMatcherName, count, lastMatchers);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.progress.ArgumentMatcherStorage#validateState()
+ */
+ public void validateState() {
+ if (!matcherStack.isEmpty()) {
+ ArrayList lastMatchers = new ArrayList<LocalizedMatcher>(matcherStack);
+ matcherStack.clear();
+ new Reporter().misplacedArgumentMatcher(lastMatchers);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.progress.ArgumentMatcherStorage#reset()
+ */
+ public void reset() {
+ matcherStack.clear();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/HandyReturnValues.java b/src/org/mockito/internal/progress/HandyReturnValues.java
new file mode 100644
index 0000000..3556621
--- /dev/null
+++ b/src/org/mockito/internal/progress/HandyReturnValues.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.progress;
+
+import java.util.*;
+
+import static org.mockito.internal.util.Primitives.defaultValueForPrimitiveOrWrapper;
+import static org.mockito.internal.util.Primitives.isPrimitiveOrWrapper;
+
+@SuppressWarnings("unchecked")
+public class HandyReturnValues {
+
+ public byte returnZero() {
+ return 0;
+ }
+
+ public char returnChar() {
+ return 0;
+ }
+
+ public <T> T returnNull() {
+ return null;
+ }
+
+ public boolean returnFalse() {
+ return false;
+ }
+
+ public String returnString() {
+ return "";
+ }
+
+ public <T> T returnFor(Class<T> clazz) {
+ // explicitly return null if type is not a primitive or a wrapper
+ if (isPrimitiveOrWrapper(clazz)) {
+ return defaultValueForPrimitiveOrWrapper(clazz);
+ }
+ return null;
+ }
+
+ public Map returnMap() {
+ return new HashMap();
+ }
+
+ public List returnList() {
+ return new LinkedList();
+ }
+
+ public Set returnSet() {
+ return new HashSet();
+ }
+
+ public <T> T returnFor(T instance) {
+ return instance == null ? null : (T) returnFor(instance.getClass());
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/IOngoingStubbing.java b/src/org/mockito/internal/progress/IOngoingStubbing.java
new file mode 100644
index 0000000..aeb5784
--- /dev/null
+++ b/src/org/mockito/internal/progress/IOngoingStubbing.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.progress;
+
+
+/**
+ * Marking interface to be removed when DeprecatedOngoingStubbing gets deleted
+ */
+public interface IOngoingStubbing {}
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/MockingProgress.java b/src/org/mockito/internal/progress/MockingProgress.java
new file mode 100644
index 0000000..36fc582
--- /dev/null
+++ b/src/org/mockito/internal/progress/MockingProgress.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.progress;
+
+import org.mockito.MockSettings;
+import org.mockito.internal.listeners.MockingProgressListener;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+@SuppressWarnings("unchecked")
+public interface MockingProgress {
+
+ void reportOngoingStubbing(IOngoingStubbing iOngoingStubbing);
+
+ IOngoingStubbing pullOngoingStubbing();
+
+ void verificationStarted(VerificationMode verificationMode);
+
+ VerificationMode pullVerificationMode();
+
+ void stubbingStarted();
+
+ void stubbingCompleted(Invocation invocation);
+
+ void validateState();
+
+ void reset();
+
+ /**
+ * Removes ongoing stubbing so that in case the framework is misused
+ * state validation errors are more accurate
+ */
+ void resetOngoingStubbing();
+
+ ArgumentMatcherStorage getArgumentMatcherStorage();
+
+ void mockingStarted(Object mock, Class classToMock);
+
+ void setListener(MockingProgressListener listener);
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/MockingProgressImpl.java b/src/org/mockito/internal/progress/MockingProgressImpl.java
new file mode 100644
index 0000000..f21b50d
--- /dev/null
+++ b/src/org/mockito/internal/progress/MockingProgressImpl.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.progress;
+
+import org.mockito.MockSettings;
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.configuration.GlobalConfiguration;
+import org.mockito.internal.debugging.Localized;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.internal.listeners.MockingProgressListener;
+import org.mockito.internal.listeners.MockingStartedListener;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+import org.mockito.verification.VerificationMode;
+
+@SuppressWarnings("unchecked")
+public class MockingProgressImpl implements MockingProgress {
+
+ private final Reporter reporter = new Reporter();
+ private final ArgumentMatcherStorage argumentMatcherStorage = new ArgumentMatcherStorageImpl();
+
+ IOngoingStubbing iOngoingStubbing;
+ private Localized<VerificationMode> verificationMode;
+ private Location stubbingInProgress = null;
+ private MockingProgressListener listener;
+
+ public void reportOngoingStubbing(IOngoingStubbing iOngoingStubbing) {
+ this.iOngoingStubbing = iOngoingStubbing;
+ }
+
+ public IOngoingStubbing pullOngoingStubbing() {
+ IOngoingStubbing temp = iOngoingStubbing;
+ iOngoingStubbing = null;
+ return temp;
+ }
+
+ public void verificationStarted(VerificationMode verify) {
+ validateState();
+ resetOngoingStubbing();
+ verificationMode = new Localized(verify);
+ }
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.progress.MockingProgress#resetOngoingStubbing()
+ */
+ public void resetOngoingStubbing() {
+ iOngoingStubbing = null;
+ }
+
+ public VerificationMode pullVerificationMode() {
+ if (verificationMode == null) {
+ return null;
+ }
+
+ VerificationMode temp = verificationMode.getObject();
+ verificationMode = null;
+ return temp;
+ }
+
+ public void stubbingStarted() {
+ validateState();
+ stubbingInProgress = new LocationImpl();
+ }
+
+ public void validateState() {
+ validateMostStuff();
+
+ //validate stubbing:
+ if (stubbingInProgress != null) {
+ Location temp = stubbingInProgress;
+ stubbingInProgress = null;
+ reporter.unfinishedStubbing(temp);
+ }
+ }
+
+ private void validateMostStuff() {
+ //State is cool when GlobalConfiguration is already loaded
+ //this cannot really be tested functionally because I cannot dynamically mess up org.mockito.configuration.MockitoConfiguration class
+ GlobalConfiguration.validate();
+
+ if (verificationMode != null) {
+ Location location = verificationMode.getLocation();
+ verificationMode = null;
+ reporter.unfinishedVerificationException(location);
+ }
+
+ getArgumentMatcherStorage().validateState();
+ }
+
+ public void stubbingCompleted(Invocation invocation) {
+ stubbingInProgress = null;
+ }
+
+ public String toString() {
+ return "iOngoingStubbing: " + iOngoingStubbing +
+ ", verificationMode: " + verificationMode +
+ ", stubbingInProgress: " + stubbingInProgress;
+ }
+
+ public void reset() {
+ stubbingInProgress = null;
+ verificationMode = null;
+ getArgumentMatcherStorage().reset();
+ }
+
+ public ArgumentMatcherStorage getArgumentMatcherStorage() {
+ return argumentMatcherStorage;
+ }
+
+ public void mockingStarted(Object mock, Class classToMock) {
+ if (listener != null && listener instanceof MockingStartedListener) {
+ ((MockingStartedListener) listener).mockingStarted(mock, classToMock);
+ }
+ validateMostStuff();
+ }
+
+ public void setListener(MockingProgressListener listener) {
+ this.listener = listener;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/SequenceNumber.java b/src/org/mockito/internal/progress/SequenceNumber.java
new file mode 100644
index 0000000..04cb006
--- /dev/null
+++ b/src/org/mockito/internal/progress/SequenceNumber.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.progress;
+
+public class SequenceNumber {
+
+ private static int sequenceNumber = 1;
+
+ public static synchronized int next() {
+ return sequenceNumber++;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/ThreadSafeMockingProgress.java b/src/org/mockito/internal/progress/ThreadSafeMockingProgress.java
new file mode 100644
index 0000000..a8a6dd3
--- /dev/null
+++ b/src/org/mockito/internal/progress/ThreadSafeMockingProgress.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.progress;
+
+import java.io.Serializable;
+
+import org.mockito.MockSettings;
+import org.mockito.internal.listeners.MockingProgressListener;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+@SuppressWarnings("unchecked")
+public class ThreadSafeMockingProgress implements MockingProgress, Serializable {
+
+ private static final long serialVersionUID = 6839454041642082618L;
+ private static ThreadLocal<MockingProgress> mockingProgress = new ThreadLocal<MockingProgress>();
+
+ static MockingProgress threadSafely() {
+ if (mockingProgress.get() == null) {
+ mockingProgress.set(new MockingProgressImpl());
+ }
+ return mockingProgress.get();
+ }
+
+ public void reportOngoingStubbing(IOngoingStubbing iOngoingStubbing) {
+ threadSafely().reportOngoingStubbing(iOngoingStubbing);
+ }
+
+ public IOngoingStubbing pullOngoingStubbing() {
+ return threadSafely().pullOngoingStubbing();
+ }
+
+ public void verificationStarted(VerificationMode verify) {
+ threadSafely().verificationStarted(verify);
+ }
+
+ public VerificationMode pullVerificationMode() {
+ return threadSafely().pullVerificationMode();
+ }
+
+ public void stubbingStarted() {
+ threadSafely().stubbingStarted();
+ }
+
+ public void validateState() {
+ threadSafely().validateState();
+ }
+
+ public void stubbingCompleted(Invocation invocation) {
+ threadSafely().stubbingCompleted(invocation);
+ }
+
+ public String toString() {
+ return threadSafely().toString();
+ }
+
+ public void reset() {
+ threadSafely().reset();
+ }
+
+ public void resetOngoingStubbing() {
+ threadSafely().resetOngoingStubbing();
+ }
+
+ public ArgumentMatcherStorage getArgumentMatcherStorage() {
+ return threadSafely().getArgumentMatcherStorage();
+ }
+
+ public void mockingStarted(Object mock, Class classToMock) {
+ threadSafely().mockingStarted(mock, classToMock);
+ }
+
+ public void setListener(MockingProgressListener listener) {
+ threadSafely().setListener(listener);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/progress/package.html b/src/org/mockito/internal/progress/package.html
new file mode 100644
index 0000000..0db3625
--- /dev/null
+++ b/src/org/mockito/internal/progress/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Mocking progress stateful classes.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/reporting/Discrepancy.java b/src/org/mockito/internal/reporting/Discrepancy.java
new file mode 100644
index 0000000..420bc5a
--- /dev/null
+++ b/src/org/mockito/internal/reporting/Discrepancy.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.reporting;
+
+public class Discrepancy {
+
+ private final int wantedCount;
+ private final int actualCount;
+
+ public Discrepancy(int wantedCount, int actualCount) {
+ this.wantedCount = wantedCount;
+ this.actualCount = actualCount;
+ }
+
+ public int getWantedCount() {
+ return wantedCount;
+ }
+
+ public String getPluralizedWantedCount() {
+ return Pluralizer.pluralize(wantedCount);
+ }
+
+ public int getActualCount() {
+ return actualCount;
+ }
+
+ public String getPluralizedActualCount() {
+ return Pluralizer.pluralize(actualCount);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/reporting/Pluralizer.java b/src/org/mockito/internal/reporting/Pluralizer.java
new file mode 100644
index 0000000..57f336a
--- /dev/null
+++ b/src/org/mockito/internal/reporting/Pluralizer.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.reporting;
+
+public class Pluralizer {
+
+ public static String pluralize(int number) {
+ return number == 1 ? "1 time" : number + " times";
+ }
+}
diff --git a/src/org/mockito/internal/reporting/PrintSettings.java b/src/org/mockito/internal/reporting/PrintSettings.java
new file mode 100644
index 0000000..63e1c6c
--- /dev/null
+++ b/src/org/mockito/internal/reporting/PrintSettings.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.reporting;
+
+import org.hamcrest.Matcher;
+import org.mockito.internal.invocation.ArgumentsProcessor;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.matchers.MatchersPrinter;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.Invocation;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+public class PrintSettings {
+
+ public static final int MAX_LINE_LENGTH = 45;
+ private boolean multiline;
+ private List<Integer> withTypeInfo = new LinkedList<Integer>();
+
+ public void setMultiline(boolean multiline) {
+ this.multiline = multiline;
+ }
+
+ public boolean isMultiline() {
+ return multiline;
+ }
+
+ public static PrintSettings verboseMatchers(Integer ... indexesOfMatchers) {
+ PrintSettings settings = new PrintSettings();
+ settings.setMatchersToBeDescribedWithExtraTypeInfo(indexesOfMatchers);
+ return settings;
+ }
+
+ public boolean extraTypeInfoFor(int argumentIndex) {
+ return withTypeInfo.contains(argumentIndex);
+ }
+
+ public void setMatchersToBeDescribedWithExtraTypeInfo(Integer[] indexesOfMatchers) {
+ this.withTypeInfo = Arrays.asList(indexesOfMatchers);
+ }
+
+ public String print(List<Matcher> matchers, Invocation invocation) {
+ MatchersPrinter matchersPrinter = new MatchersPrinter();
+ String qualifiedName = new MockUtil().getMockName(invocation.getMock()) + "." + invocation.getMethod().getName();
+ String invocationString = qualifiedName + matchersPrinter.getArgumentsLine(matchers, this);
+ if (isMultiline() || (!matchers.isEmpty() && invocationString.length() > MAX_LINE_LENGTH)) {
+ return qualifiedName + matchersPrinter.getArgumentsBlock(matchers, this);
+ } else {
+ return invocationString;
+ }
+ }
+
+ public String print(Invocation invocation) {
+ return print(ArgumentsProcessor.argumentsToMatchers(invocation.getArguments()), invocation);
+ }
+
+ public String print(InvocationMatcher invocationMatcher) {
+ return print(invocationMatcher.getMatchers(), invocationMatcher.getInvocation());
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/reporting/SmartPrinter.java b/src/org/mockito/internal/reporting/SmartPrinter.java
new file mode 100644
index 0000000..c59492c
--- /dev/null
+++ b/src/org/mockito/internal/reporting/SmartPrinter.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.reporting;
+
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+/**
+ * Makes sure both wanted and actual are printed consistently (single line or multiline)
+ * <p>
+ * Makes arguments printed with types if necessary
+ */
+public class SmartPrinter {
+
+ private final String wanted;
+ private final String actual;
+
+ public SmartPrinter(InvocationMatcher wanted, Invocation actual, Integer ... indexesOfMatchersToBeDescribedWithExtraTypeInfo) {
+ PrintSettings printSettings = new PrintSettings();
+ printSettings.setMultiline(wanted.toString().contains("\n") || actual.toString().contains("\n"));
+ printSettings.setMatchersToBeDescribedWithExtraTypeInfo(indexesOfMatchersToBeDescribedWithExtraTypeInfo);
+
+ this.wanted = printSettings.print(wanted);
+ this.actual = printSettings.print(actual);
+ }
+
+ public String getWanted() {
+ return wanted;
+ }
+
+ public String getActual() {
+ return actual;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/reporting/package.html b/src/org/mockito/internal/reporting/package.html
new file mode 100644
index 0000000..92b9096
--- /dev/null
+++ b/src/org/mockito/internal/reporting/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Deals with nicely printing verification errors
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/runners/JUnit44RunnerImpl.java b/src/org/mockito/internal/runners/JUnit44RunnerImpl.java
new file mode 100644
index 0000000..2180a97
--- /dev/null
+++ b/src/org/mockito/internal/runners/JUnit44RunnerImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.runners;
+
+import org.junit.internal.runners.InitializationError;
+import org.junit.internal.runners.JUnit4ClassRunner;
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.runners.util.FrameworkUsageValidator;
+
+@SuppressWarnings("deprecation")
+public class JUnit44RunnerImpl implements RunnerImpl {
+
+ JUnit4ClassRunner runner;
+
+ public JUnit44RunnerImpl(Class<?> klass) throws InitializationError {
+ this.runner = new JUnit4ClassRunner(klass) {
+ @Override
+ protected Object createTest() throws Exception {
+ Object test = super.createTest();
+ MockitoAnnotations.initMocks(test);
+ return test;
+ }
+ };
+ }
+
+ public void run(RunNotifier notifier) {
+ // add listener that validates framework usage at the end of each test
+ notifier.addListener(new FrameworkUsageValidator(notifier));
+
+ runner.run(notifier);
+ }
+
+ public Description getDescription() {
+ return runner.getDescription();
+ }
+
+ public void filter(Filter filter) throws NoTestsRemainException {
+ runner.filter(filter);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/runners/JUnit45AndHigherRunnerImpl.java b/src/org/mockito/internal/runners/JUnit45AndHigherRunnerImpl.java
new file mode 100644
index 0000000..700c659
--- /dev/null
+++ b/src/org/mockito/internal/runners/JUnit45AndHigherRunnerImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.runners.util.FrameworkUsageValidator;
+
+public class JUnit45AndHigherRunnerImpl implements RunnerImpl {
+
+ private BlockJUnit4ClassRunner runner;
+
+ public JUnit45AndHigherRunnerImpl(Class<?> klass) throws InitializationError {
+ runner = new BlockJUnit4ClassRunner(klass) {
+ protected Statement withBefores(FrameworkMethod method, Object target,
+ Statement statement) {
+ // init annotated mocks before tests
+ MockitoAnnotations.initMocks(target);
+ return super.withBefores(method, target, statement);
+ }
+ };
+ }
+
+ public void run(final RunNotifier notifier) {
+ // add listener that validates framework usage at the end of each test
+ notifier.addListener(new FrameworkUsageValidator(notifier));
+
+ runner.run(notifier);
+ }
+
+ public Description getDescription() {
+ return runner.getDescription();
+ }
+
+ public void filter(Filter filter) throws NoTestsRemainException {
+ runner.filter(filter);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/runners/RunnerFactory.java b/src/org/mockito/internal/runners/RunnerFactory.java
new file mode 100644
index 0000000..871e607
--- /dev/null
+++ b/src/org/mockito/internal/runners/RunnerFactory.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.runners.util.RunnerProvider;
+import org.mockito.internal.runners.util.TestMethodsFinder;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class RunnerFactory {
+
+ private final RunnerProvider runnerProvider;
+
+ RunnerFactory(RunnerProvider runnerProvider) {
+ this.runnerProvider = runnerProvider;
+ }
+
+ public RunnerFactory() {
+ this(new RunnerProvider());
+ }
+
+ public RunnerImpl create(Class<?> klass) throws InvocationTargetException {
+ try {
+ if (runnerProvider.isJUnit45OrHigherAvailable()) {
+ return runnerProvider.newInstance("org.mockito.internal.runners.JUnit45AndHigherRunnerImpl", klass);
+ } else {
+ return runnerProvider.newInstance("org.mockito.internal.runners.JUnit44RunnerImpl", klass);
+ }
+ } catch (InvocationTargetException e) {
+ if (!new TestMethodsFinder().hasTestMethods(klass)) {
+ throw new MockitoException(
+ "\n" +
+ "\n" +
+ "No tests found in " + klass.getSimpleName() + "\n" +
+ "Haven't you forgot @Test annotation?\n"
+ , e);
+ }
+ throw e;
+ } catch (Throwable t) {
+ throw new MockitoException(
+ "\n" +
+ "\n" +
+ "MockitoRunner can only be used with JUnit 4.4 or higher.\n" +
+ "You can upgrade your JUnit version or write your own Runner (please consider contributing your runner to the Mockito community).\n" +
+ "Bear in mind that you can still enjoy all features of the framework without using runners (they are completely optional).\n" +
+ "If you get this error despite using JUnit 4.4 or higher then please report this error to the mockito mailing list.\n"
+ , t);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/runners/RunnerImpl.java b/src/org/mockito/internal/runners/RunnerImpl.java
new file mode 100644
index 0000000..a723b88
--- /dev/null
+++ b/src/org/mockito/internal/runners/RunnerImpl.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.notification.RunNotifier;
+
+/**
+ * I'm using this surrogate interface to hide internal Runner implementations.
+ * Surrogate cannot be used with @RunWith therefore it is less likely clients will use interal runners.
+ */
+public interface RunnerImpl extends Filterable{
+
+ void run(RunNotifier notifier);
+
+ Description getDescription();
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/runners/package.html b/src/org/mockito/internal/runners/package.html
new file mode 100644
index 0000000..6a1b89e
--- /dev/null
+++ b/src/org/mockito/internal/runners/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Internal classes for runners implementations
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/runners/util/FrameworkUsageValidator.java b/src/org/mockito/internal/runners/util/FrameworkUsageValidator.java
new file mode 100644
index 0000000..64edc48
--- /dev/null
+++ b/src/org/mockito/internal/runners/util/FrameworkUsageValidator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners.util;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.Mockito;
+
+public class FrameworkUsageValidator extends RunListener {
+
+ private final RunNotifier notifier;
+
+ public FrameworkUsageValidator(RunNotifier notifier) {
+ this.notifier = notifier;
+ }
+
+ @Override
+ public void testFinished(Description description) throws Exception {
+ super.testFinished(description);
+ try {
+ Mockito.validateMockitoUsage();
+ } catch(Throwable t) {
+ notifier.fireTestFailure(new Failure(description, t));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/runners/util/RunnerProvider.java b/src/org/mockito/internal/runners/util/RunnerProvider.java
new file mode 100644
index 0000000..8ae12d7
--- /dev/null
+++ b/src/org/mockito/internal/runners/util/RunnerProvider.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.mockito.internal.runners.RunnerImpl;
+
+public class RunnerProvider {
+
+ private static boolean hasJUnit45OrHigher;
+
+ static {
+ try {
+ Class.forName("org.junit.runners.BlockJUnit4ClassRunner");
+ hasJUnit45OrHigher = true;
+ } catch (Throwable t) {
+ hasJUnit45OrHigher = false;
+ }
+ }
+
+ public boolean isJUnit45OrHigherAvailable() {
+ return hasJUnit45OrHigher;
+ }
+
+ public RunnerImpl newInstance(String runnerClassName, Class<?> constructorParam) throws Exception {
+ Constructor<?> constructor;
+ try {
+ Class<?> runnerClass = Class.forName(runnerClassName);
+ constructor = runnerClass.getConstructor(Class.class.getClass());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ try {
+ return (RunnerImpl) constructor.newInstance(constructorParam);
+ } catch (InvocationTargetException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/runners/util/TestMethodsFinder.java b/src/org/mockito/internal/runners/util/TestMethodsFinder.java
new file mode 100644
index 0000000..3becfe2
--- /dev/null
+++ b/src/org/mockito/internal/runners/util/TestMethodsFinder.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.runners.util;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+public class TestMethodsFinder {
+ public boolean hasTestMethods(Class<?> klass) {
+ Method[] methods = klass.getMethods();
+ for(Method m:methods) {
+ if (m.isAnnotationPresent(Test.class)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/org/mockito/internal/runners/util/package.html b/src/org/mockito/internal/runners/util/package.html
new file mode 100644
index 0000000..b6c4110
--- /dev/null
+++ b/src/org/mockito/internal/runners/util/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Internal utils for runner implementations
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/BaseStubbing.java b/src/org/mockito/internal/stubbing/BaseStubbing.java
new file mode 100644
index 0000000..401cf9f
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/BaseStubbing.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.internal.stubbing.answers.ThrowsExceptionClass;
+import org.mockito.stubbing.DeprecatedOngoingStubbing;
+import org.mockito.stubbing.OngoingStubbing;
+
+public abstract class BaseStubbing<T> implements OngoingStubbing<T>, DeprecatedOngoingStubbing<T> {
+ public OngoingStubbing<T> thenReturn(T value) {
+ return thenAnswer(new Returns(value));
+ }
+
+ public OngoingStubbing<T> thenReturn(T value, T... values) {
+ OngoingStubbing<T> stubbing = thenReturn(value);
+ if (values == null) {
+ return stubbing.thenReturn(null);
+ }
+ for (T v: values) {
+ stubbing = stubbing.thenReturn(v);
+ }
+ return stubbing;
+ }
+
+ private OngoingStubbing<T> thenThrow(Throwable throwable) {
+ return thenAnswer(new ThrowsException(throwable));
+ }
+
+ public OngoingStubbing<T> thenThrow(Throwable... throwables) {
+ if (throwables == null) {
+ thenThrow((Throwable) null);
+ }
+ OngoingStubbing<T> stubbing = null;
+ for (Throwable t: throwables) {
+ if (stubbing == null) {
+ stubbing = thenThrow(t);
+ } else {
+ stubbing = stubbing.thenThrow(t);
+ }
+ }
+ return stubbing;
+ }
+
+ private OngoingStubbing<T> thenThrow(Class<? extends Throwable> throwableClass) {
+ return thenAnswer(new ThrowsExceptionClass(throwableClass));
+ }
+
+ public OngoingStubbing<T> thenThrow(Class<? extends Throwable>... throwableClasses) {
+ if (throwableClasses == null) {
+ thenThrow((Throwable) null);
+ }
+ OngoingStubbing<T> stubbing = null;
+ for (Class<? extends Throwable> t: throwableClasses) {
+ if (stubbing == null) {
+ stubbing = thenThrow(t);
+ } else {
+ stubbing = stubbing.thenThrow(t);
+ }
+ }
+ return stubbing;
+ }
+
+ public OngoingStubbing<T> thenCallRealMethod() {
+ return thenAnswer(new CallsRealMethods());
+ }
+
+ public DeprecatedOngoingStubbing<T> toReturn(T value) {
+ return toAnswer(new Returns(value));
+ }
+
+ public DeprecatedOngoingStubbing<T> toThrow(Throwable throwable) {
+ return toAnswer(new ThrowsException(throwable));
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/ConsecutiveStubbing.java b/src/org/mockito/internal/stubbing/ConsecutiveStubbing.java
new file mode 100644
index 0000000..2541f63
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/ConsecutiveStubbing.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.DeprecatedOngoingStubbing;
+import org.mockito.stubbing.OngoingStubbing;
+
+public class ConsecutiveStubbing<T> extends BaseStubbing<T> {
+ private final InvocationContainerImpl invocationContainerImpl;
+
+ public ConsecutiveStubbing(InvocationContainerImpl invocationContainerImpl) {
+ this.invocationContainerImpl = invocationContainerImpl;
+ }
+
+ public OngoingStubbing<T> thenAnswer(Answer<?> answer) {
+ invocationContainerImpl.addConsecutiveAnswer(answer);
+ return this;
+ }
+
+ public OngoingStubbing<T> then(Answer<?> answer) {
+ return thenAnswer(answer);
+ }
+
+ public DeprecatedOngoingStubbing<T> toAnswer(Answer<?> answer) {
+ invocationContainerImpl.addConsecutiveAnswer(answer);
+ return this;
+ }
+
+ public <M> M getMock() {
+ return (M) invocationContainerImpl.invokedMock();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/InvocationContainer.java b/src/org/mockito/internal/stubbing/InvocationContainer.java
new file mode 100644
index 0000000..783ec55
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/InvocationContainer.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+//TODO move to different package
+public interface InvocationContainer {
+ List<Invocation> getInvocations();
+
+ List<StubbedInvocationMatcher> getStubbedInvocations();
+}
diff --git a/src/org/mockito/internal/stubbing/InvocationContainerImpl.java b/src/org/mockito/internal/stubbing/InvocationContainerImpl.java
new file mode 100644
index 0000000..3d45e6c
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/InvocationContainerImpl.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.StubInfoImpl;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.stubbing.answers.AnswersValidator;
+import org.mockito.internal.verification.DefaultRegisteredInvocations;
+import org.mockito.internal.verification.RegisteredInvocations;
+import org.mockito.internal.verification.SingleRegisteredInvocation;
+import org.mockito.invocation.Invocation;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class InvocationContainerImpl implements InvocationContainer, Serializable {
+
+ private static final long serialVersionUID = -5334301962749537177L;
+ private final LinkedList<StubbedInvocationMatcher> stubbed = new LinkedList<StubbedInvocationMatcher>();
+ private final MockingProgress mockingProgress;
+ private final List<Answer> answersForStubbing = new ArrayList<Answer>();
+ private final RegisteredInvocations registeredInvocations;
+
+ private InvocationMatcher invocationForStubbing;
+
+ public InvocationContainerImpl(MockingProgress mockingProgress, MockCreationSettings mockSettings) {
+ this.mockingProgress = mockingProgress;
+ this.registeredInvocations = createRegisteredInvocations(mockSettings);
+ }
+
+ public void setInvocationForPotentialStubbing(InvocationMatcher invocation) {
+ registeredInvocations.add(invocation.getInvocation());
+ this.invocationForStubbing = invocation;
+ }
+
+ public void resetInvocationForPotentialStubbing(InvocationMatcher invocationMatcher) {
+ this.invocationForStubbing = invocationMatcher;
+ }
+
+ public void addAnswer(Answer answer) {
+ registeredInvocations.removeLast();
+ addAnswer(answer, false);
+ }
+
+ public void addConsecutiveAnswer(Answer answer) {
+ addAnswer(answer, true);
+ }
+
+ public void addAnswer(Answer answer, boolean isConsecutive) {
+ Invocation invocation = invocationForStubbing.getInvocation();
+ mockingProgress.stubbingCompleted(invocation);
+ AnswersValidator answersValidator = new AnswersValidator();
+ answersValidator.validate(answer, invocation);
+
+ synchronized (stubbed) {
+ if (isConsecutive) {
+ stubbed.getFirst().addAnswer(answer);
+ } else {
+ stubbed.addFirst(new StubbedInvocationMatcher(invocationForStubbing, answer));
+ }
+ }
+ }
+
+ Object answerTo(Invocation invocation) throws Throwable {
+ return findAnswerFor(invocation).answer(invocation);
+ }
+
+ public StubbedInvocationMatcher findAnswerFor(Invocation invocation) {
+ synchronized (stubbed) {
+ for (StubbedInvocationMatcher s : stubbed) {
+ if (s.matches(invocation)) {
+ s.markStubUsed(invocation);
+ invocation.markStubbed(new StubInfoImpl(s));
+ return s;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public void addAnswerForVoidMethod(Answer answer) {
+ answersForStubbing.add(answer);
+ }
+
+ public void setAnswersForStubbing(List<Answer> answers) {
+ answersForStubbing.addAll(answers);
+ }
+
+ public boolean hasAnswersForStubbing() {
+ return !answersForStubbing.isEmpty();
+ }
+
+ public boolean hasInvocationForPotentialStubbing() {
+ return !registeredInvocations.isEmpty();
+ }
+
+ public void setMethodForStubbing(InvocationMatcher invocation) {
+ invocationForStubbing = invocation;
+ assert hasAnswersForStubbing();
+ for (int i = 0; i < answersForStubbing.size(); i++) {
+ addAnswer(answersForStubbing.get(i), i != 0);
+ }
+ answersForStubbing.clear();
+ }
+
+ @Override
+ public String toString() {
+ return "invocationForStubbing: " + invocationForStubbing;
+ }
+
+ public List<Invocation> getInvocations() {
+ return registeredInvocations.getAll();
+ }
+
+ public List<StubbedInvocationMatcher> getStubbedInvocations() {
+ return stubbed;
+ }
+
+ public Object invokedMock() {
+ return invocationForStubbing.getInvocation().getMock();
+ }
+
+ public InvocationMatcher getInvocationForStubbing() {
+ return invocationForStubbing;
+ }
+
+ private RegisteredInvocations createRegisteredInvocations(MockCreationSettings mockSettings) {
+ return mockSettings.isStubOnly()
+ ? new SingleRegisteredInvocation()
+ : new DefaultRegisteredInvocations();
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/OngoingStubbingImpl.java b/src/org/mockito/internal/stubbing/OngoingStubbingImpl.java
new file mode 100644
index 0000000..8be71d7
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/OngoingStubbingImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.invocation.Invocation;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.DeprecatedOngoingStubbing;
+import org.mockito.stubbing.OngoingStubbing;
+
+import java.util.List;
+
+public class OngoingStubbingImpl<T> extends BaseStubbing<T> {
+
+ private final InvocationContainerImpl invocationContainerImpl;
+
+ public OngoingStubbingImpl(InvocationContainerImpl invocationContainerImpl) {
+ this.invocationContainerImpl = invocationContainerImpl;
+ }
+
+ public OngoingStubbing<T> thenAnswer(Answer<?> answer) {
+ if(!invocationContainerImpl.hasInvocationForPotentialStubbing()) {
+ new Reporter().incorrectUseOfApi();
+ }
+
+ invocationContainerImpl.addAnswer(answer);
+ return new ConsecutiveStubbing<T>(invocationContainerImpl);
+ }
+
+ public OngoingStubbing<T> then(Answer<?> answer) {
+ return thenAnswer(answer);
+ }
+
+ public DeprecatedOngoingStubbing<T> toAnswer(Answer<?> answer) {
+ invocationContainerImpl.addAnswer(answer);
+ return new ConsecutiveStubbing<T>(invocationContainerImpl);
+ }
+
+ public List<Invocation> getRegisteredInvocations() {
+ //TODO interface for tests
+ return invocationContainerImpl.getInvocations();
+ }
+
+ public <M> M getMock() {
+ return (M) invocationContainerImpl.invokedMock();
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/StubbedInvocationMatcher.java b/src/org/mockito/internal/stubbing/StubbedInvocationMatcher.java
new file mode 100644
index 0000000..9a7cefb
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/StubbedInvocationMatcher.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import java.io.Serializable;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.DescribedInvocation;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+@SuppressWarnings("unchecked")
+public class StubbedInvocationMatcher extends InvocationMatcher implements Answer, Serializable {
+
+ private static final long serialVersionUID = 4919105134123672727L;
+ private final Queue<Answer> answers = new ConcurrentLinkedQueue<Answer>();
+ private DescribedInvocation usedAt;
+
+ public StubbedInvocationMatcher(InvocationMatcher invocation, Answer answer) {
+ super(invocation.getInvocation(), invocation.getMatchers());
+ this.answers.add(answer);
+ }
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ //see ThreadsShareGenerouslyStubbedMockTest
+ Answer a;
+ synchronized(answers) {
+ a = answers.size() == 1 ? answers.peek() : answers.poll();
+ }
+ return a.answer(invocation);
+ }
+
+ public void addAnswer(Answer answer) {
+ answers.add(answer);
+ }
+
+ public void markStubUsed(DescribedInvocation usedAt) {
+ this.usedAt = usedAt;
+ }
+
+ public boolean wasUsed() {
+ return usedAt != null;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " stubbed with: " + answers;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/StubberImpl.java b/src/org/mockito/internal/stubbing/StubberImpl.java
new file mode 100644
index 0000000..ac8fb2e
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/StubberImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.stubbing.answers.*;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Stubber;
+
+import java.util.LinkedList;
+import java.util.List;
+
+@SuppressWarnings("unchecked")
+public class StubberImpl implements Stubber {
+
+ final List<Answer> answers = new LinkedList<Answer>();
+ private final Reporter reporter = new Reporter();
+
+ public <T> T when(T mock) {
+ MockUtil mockUtil = new MockUtil();
+
+ if (mock == null) {
+ reporter.nullPassedToWhenMethod();
+ } else {
+ if (!mockUtil.isMock(mock)) {
+ reporter.notAMockPassedToWhenMethod();
+ }
+ }
+
+ mockUtil.getMockHandler(mock).setAnswersForStubbing(answers);
+ return mock;
+ }
+
+ public Stubber doReturn(Object toBeReturned) {
+ answers.add(new Returns(toBeReturned));
+ return this;
+ }
+
+ public Stubber doThrow(Throwable toBeThrown) {
+ answers.add(new ThrowsException(toBeThrown));
+ return this;
+ }
+
+ public Stubber doThrow(Class<? extends Throwable> toBeThrown) {
+ answers.add(new ThrowsExceptionClass(toBeThrown));
+ return this;
+ }
+
+ public Stubber doNothing() {
+ answers.add(new DoesNothing());
+ return this;
+ }
+
+ public Stubber doAnswer(Answer answer) {
+ answers.add(answer);
+ return this;
+ }
+
+ public Stubber doCallRealMethod() {
+ answers.add(new CallsRealMethods());
+ return this;
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/VoidMethodStubbableImpl.java b/src/org/mockito/internal/stubbing/VoidMethodStubbableImpl.java
new file mode 100644
index 0000000..3859fed
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/VoidMethodStubbableImpl.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing;
+
+import org.mockito.internal.stubbing.answers.DoesNothing;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.VoidMethodStubbable;
+
+public class VoidMethodStubbableImpl<T> implements VoidMethodStubbable<T> {
+ private final T mock;
+ private InvocationContainerImpl invocationContainerImpl;
+
+ public VoidMethodStubbableImpl(T mock, InvocationContainerImpl invocationContainerImpl) {
+ this.mock = mock;
+ this.invocationContainerImpl = invocationContainerImpl;
+ }
+
+ public VoidMethodStubbable<T> toThrow(Throwable throwable) {
+ invocationContainerImpl.addAnswerForVoidMethod(new ThrowsException(throwable));
+ return this;
+ }
+
+ public VoidMethodStubbable<T> toReturn() {
+ invocationContainerImpl.addAnswerForVoidMethod(new DoesNothing());
+ return this;
+ }
+
+ public VoidMethodStubbable<T> toAnswer(Answer<?> answer) {
+ invocationContainerImpl.addAnswerForVoidMethod(answer);
+ return this;
+ }
+
+ public T on() {
+ return mock;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/AnswerReturnValuesAdapter.java b/src/org/mockito/internal/stubbing/answers/AnswerReturnValuesAdapter.java
new file mode 100644
index 0000000..76510cd
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/AnswerReturnValuesAdapter.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.io.Serializable;
+
+import org.mockito.ReturnValues;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+//It's ok to suppress deprecation because this class goes away as soon as ReturnValues disappears in future release
+@SuppressWarnings("deprecation")
+public class AnswerReturnValuesAdapter implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = 1418158596876713469L;
+ private final ReturnValues returnValues;
+
+ public AnswerReturnValuesAdapter(ReturnValues returnValues) {
+ this.returnValues = returnValues;
+ }
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return returnValues.valueFor(invocation);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/AnswersValidator.java b/src/org/mockito/internal/stubbing/answers/AnswersValidator.java
new file mode 100644
index 0000000..b8f5b7a
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/AnswersValidator.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.invocation.Invocation;
+import org.mockito.stubbing.Answer;
+
+public class AnswersValidator {
+
+ private Reporter reporter = new Reporter();
+
+ public void validate(Answer<?> answer, Invocation invocation) {
+ MethodInfo methodInfo = new MethodInfo(invocation);
+ if (answer instanceof ThrowsException) {
+ validateException((ThrowsException) answer, methodInfo);
+ }
+
+ if (answer instanceof Returns) {
+ validateReturnValue((Returns) answer, methodInfo);
+ }
+
+ if (answer instanceof DoesNothing) {
+ validateDoNothing((DoesNothing) answer, methodInfo);
+ }
+
+ if (answer instanceof CallsRealMethods) {
+ validateMockingConcreteClass((CallsRealMethods) answer, methodInfo);
+ }
+
+ if (answer instanceof ReturnsArgumentAt) {
+ ReturnsArgumentAt returnsArgumentAt = (ReturnsArgumentAt) answer;
+ validateReturnArgIdentity(returnsArgumentAt, invocation);
+ }
+ }
+
+ private void validateReturnArgIdentity(ReturnsArgumentAt returnsArgumentAt, Invocation invocation) {
+ returnsArgumentAt.validateIndexWithinInvocationRange(invocation);
+
+ MethodInfo methodInfo = new MethodInfo(invocation);
+ if (!methodInfo.isValidReturnType(returnsArgumentAt.returnedTypeOnSignature(invocation))) {
+ new Reporter().wrongTypeOfArgumentToReturn(invocation, methodInfo.printMethodReturnType(),
+ returnsArgumentAt.returnedTypeOnSignature(invocation),
+ returnsArgumentAt.wantedArgumentPosition());
+ }
+
+ }
+
+ private void validateMockingConcreteClass(CallsRealMethods answer, MethodInfo methodInfo) {
+ if (methodInfo.isDeclaredOnInterface()) {
+ reporter.cannotCallRealMethodOnInterface();
+ }
+ }
+
+ private void validateDoNothing(DoesNothing answer, MethodInfo methodInfo) {
+ if (!methodInfo.isVoid()) {
+ reporter.onlyVoidMethodsCanBeSetToDoNothing();
+ }
+ }
+
+ private void validateReturnValue(Returns answer, MethodInfo methodInfo) {
+ if (methodInfo.isVoid()) {
+ reporter.cannotStubVoidMethodWithAReturnValue(methodInfo.getMethodName());
+ }
+
+ if (answer.returnsNull() && methodInfo.returnsPrimitive()) {
+ reporter.wrongTypeOfReturnValue(methodInfo.printMethodReturnType(), "null", methodInfo.getMethodName());
+ }
+
+ if (!answer.returnsNull() && !methodInfo.isValidReturnType(answer.getReturnType())) {
+ reporter.wrongTypeOfReturnValue(methodInfo.printMethodReturnType(), answer.printReturnType(), methodInfo.getMethodName());
+ }
+ }
+
+ private void validateException(ThrowsException answer, MethodInfo methodInfo) {
+ Throwable throwable = answer.getThrowable();
+ if (throwable == null) {
+ reporter.cannotStubWithNullThrowable();
+ }
+
+ if (throwable instanceof RuntimeException || throwable instanceof Error) {
+ return;
+ }
+
+ if (!methodInfo.isValidException(throwable)) {
+ reporter.checkedExceptionInvalid(throwable);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/CallsRealMethods.java b/src/org/mockito/internal/stubbing/answers/CallsRealMethods.java
new file mode 100644
index 0000000..14e12dd
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/CallsRealMethods.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.io.Serializable;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Optional Answer that adds partial mocking support
+ * <p>
+ * {@link Answer} can be used to define the return values of unstubbed invocations.
+ * <p>
+ * This implementation can be helpful when working with legacy code.
+ * When this implementation is used, unstubbed methods will delegate to the real implementation.
+ * This is a way to create a partial mock object that calls real methods by default.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ * <p>
+ */
+public class CallsRealMethods implements Answer<Object>, Serializable {
+ private static final long serialVersionUID = 9057165148930624087L;
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return invocation.callRealMethod();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/ClonesArguments.java b/src/org/mockito/internal/stubbing/answers/ClonesArguments.java
new file mode 100644
index 0000000..f6fa264
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/ClonesArguments.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
+import org.mockito.internal.util.reflection.LenientCopyTool;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.objenesis.ObjenesisHelper;
+
+//TODO this needs documentation and further analysis - what if someone changes the answer?
+//we might think about implementing it straight on MockSettings
+public class ClonesArguments implements Answer<Object> {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Object[] arguments = invocation.getArguments();
+ for (int i = 0; i < arguments.length; i++) {
+ Object from = arguments[i];
+ Object newInstance = ObjenesisHelper.newInstance(from.getClass());
+ new LenientCopyTool().copyToRealObject(from, newInstance);
+ arguments[i] = newInstance;
+ }
+ return new ReturnsEmptyValues().answer(invocation);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/DoesNothing.java b/src/org/mockito/internal/stubbing/answers/DoesNothing.java
new file mode 100644
index 0000000..d9a7d7a
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/DoesNothing.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.io.Serializable;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class DoesNothing implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = 4840880517740698416L;
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/MethodInfo.java b/src/org/mockito/internal/stubbing/answers/MethodInfo.java
new file mode 100644
index 0000000..a27e0bb
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/MethodInfo.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.internal.util.Primitives;
+import org.mockito.invocation.Invocation;
+
+import java.lang.reflect.Method;
+
+/**
+ * by Szczepan Faber, created at: 3/31/12
+ */
+public class MethodInfo {
+
+ private Method method;
+
+ public MethodInfo(Invocation theInvocation) {
+ this.method = theInvocation.getMethod();
+ }
+
+ public boolean isValidException(Throwable throwable) {
+ Class<?>[] exceptions = method.getExceptionTypes();
+ Class<?> throwableClass = throwable.getClass();
+ for (Class<?> exception : exceptions) {
+ if (exception.isAssignableFrom(throwableClass)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean isValidReturnType(Class clazz) {
+ if (method.getReturnType().isPrimitive() || clazz.isPrimitive()) {
+ return Primitives.primitiveTypeOf(clazz) == Primitives.primitiveTypeOf(method.getReturnType());
+ } else {
+ return method.getReturnType().isAssignableFrom(clazz);
+ }
+ }
+
+ public boolean isVoid() {
+ return this.method.getReturnType() == Void.TYPE;
+ }
+
+ public String printMethodReturnType() {
+ return method.getReturnType().getSimpleName();
+ }
+
+ public String getMethodName() {
+ return method.getName();
+ }
+
+ public boolean returnsPrimitive() {
+ return method.getReturnType().isPrimitive();
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ public boolean isDeclaredOnInterface() {
+ return method.getDeclaringClass().isInterface();
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/answers/Returns.java b/src/org/mockito/internal/stubbing/answers/Returns.java
new file mode 100644
index 0000000..b0ad9fa
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/Returns.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import java.io.Serializable;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class Returns implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = -6245608253574215396L;
+ private final Object value;
+
+ public Returns(Object value) {
+ this.value = value;
+ }
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return value;
+ }
+
+ public String printReturnType() {
+ return value.getClass().getSimpleName();
+ }
+
+ public Class<?> getReturnType() {
+ return value.getClass();
+ }
+
+ public boolean returnsNull() {
+ return value == null;
+ }
+
+ @Override
+ public String toString() {
+ return "Returns: " + value;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java b/src/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java
new file mode 100644
index 0000000..059074d
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+
+/**
+ * Returns the passed parameter identity at specified index.
+ *
+ * <p>The <code>argumentIndex</code> represents the index in the argument array of the invocation.</p>
+ * <p>If this number equals -1 then the last argument is returned.</p>
+ *
+ * @see org.mockito.AdditionalAnswers
+ * @since 1.9.5
+ */
+public class ReturnsArgumentAt implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = -589315085166295101L;
+
+ public static final int LAST_ARGUMENT = -1;
+
+ private final int wantedArgumentPosition;
+
+ /**
+ * Build the identity answer to return the argument at the given position in the argument array.
+ *
+ * @param wantedArgumentPosition The position of the argument identity to return in the invocation.
+ * Using <code>-1</code> indicates the last argument.
+ */
+ public ReturnsArgumentAt(int wantedArgumentPosition) {
+ this.wantedArgumentPosition = checkWithinAllowedRange(wantedArgumentPosition);
+ }
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ validateIndexWithinInvocationRange(invocation);
+ return invocation.getArguments()[actualArgumentPosition(invocation)];
+ }
+
+
+ private int actualArgumentPosition(InvocationOnMock invocation) {
+ return returningLastArg() ?
+ lastArgumentIndexOf(invocation) :
+ argumentIndexOf(invocation);
+ }
+
+ private boolean returningLastArg() {
+ return wantedArgumentPosition == LAST_ARGUMENT;
+ }
+
+ private int argumentIndexOf(InvocationOnMock invocation) {
+ return wantedArgumentPosition;
+ }
+
+ private int lastArgumentIndexOf(InvocationOnMock invocation) {
+ return invocation.getArguments().length - 1;
+ }
+
+ private int checkWithinAllowedRange(int argumentPosition) {
+ if (argumentPosition != LAST_ARGUMENT && argumentPosition < 0) {
+ new Reporter().invalidArgumentRangeAtIdentityAnswerCreationTime();
+ }
+ return argumentPosition;
+ }
+
+ public int wantedArgumentPosition() {
+ return wantedArgumentPosition;
+ }
+
+ public void validateIndexWithinInvocationRange(InvocationOnMock invocation) {
+ if (!argumentPositionInRange(invocation)) {
+ new Reporter().invalidArgumentPositionRangeAtInvocationTime(invocation,
+ returningLastArg(),
+ wantedArgumentPosition);
+ }
+ }
+
+ private boolean argumentPositionInRange(InvocationOnMock invocation) {
+ int actualArgumentPosition = actualArgumentPosition(invocation);
+ if (actualArgumentPosition < 0) {
+ return false;
+ }
+ if (!invocation.getMethod().isVarArgs()) {
+ return invocation.getArguments().length > actualArgumentPosition;
+ }
+ // for all varargs accepts positive ranges
+ return true;
+ }
+
+ public Class returnedTypeOnSignature(InvocationOnMock invocation) {
+ int actualArgumentPosition = actualArgumentPosition(invocation);
+
+ if(!invocation.getMethod().isVarArgs()) {
+ return invocation.getMethod().getParameterTypes()[actualArgumentPosition];
+ }
+
+ Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
+ int varargPosition = parameterTypes.length - 1;
+
+ if(actualArgumentPosition < varargPosition) {
+ return parameterTypes[actualArgumentPosition];
+ } else {
+ return parameterTypes[varargPosition].getComponentType();
+ }
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java b/src/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java
new file mode 100644
index 0000000..b6e1659
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * Returns elements of the collection. Keeps returning the last element forever.
+ * Might be useful on occasion when you have a collection of elements to return.
+ * <p>
+ * <pre class="code"><code class="java">
+ * //this:
+ * when(mock.foo()).thenReturn(1, 2, 3);
+ * //is equivalent to:
+ * when(mock.foo()).thenAnswer(new ReturnsElementsOf(Arrays.asList(1, 2, 3)));
+ * </code></pre>
+ * </p>
+ *
+ * <p>
+ * Also you might better want to use the static factory there
+ * {@link org.mockito.AdditionalAnswers#returnsElementsOf(java.util.Collection)}
+ * </p>
+ *
+ * @see org.mockito.AdditionalAnswers
+ */
+public class ReturnsElementsOf implements Answer<Object> {
+
+ private final LinkedList<Object> elements;
+
+ public ReturnsElementsOf(Collection<?> elements) {
+ if (elements == null) {
+ throw new MockitoException("ReturnsElementsOf does not accept null as constructor argument.\n" +
+ "Please pass a collection instance");
+ }
+ this.elements = new LinkedList<Object>(elements);
+ }
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ if (elements.size() == 1)
+ return elements.get(0);
+ else
+ return elements.poll();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/ThrowsException.java b/src/org/mockito/internal/stubbing/answers/ThrowsException.java
new file mode 100644
index 0000000..b1ed1b2
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/ThrowsException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+
+public class ThrowsException implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = 1128820328555183980L;
+ private final Throwable throwable;
+ private final ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
+
+ public ThrowsException(Throwable throwable) {
+ this.throwable = throwable;
+ }
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ if (new MockUtil().isMock(throwable)) {
+ throw throwable;
+ }
+ Throwable t = throwable.fillInStackTrace();
+ filter.filter(t);
+ throw t;
+ }
+
+ public Throwable getThrowable() {
+ return throwable;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/answers/ThrowsExceptionClass.java b/src/org/mockito/internal/stubbing/answers/ThrowsExceptionClass.java
new file mode 100644
index 0000000..3b1af82
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/ThrowsExceptionClass.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.stubbing.answers;
+
+import org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.objenesis.ObjenesisHelper;
+
+import java.io.Serializable;
+
+public class ThrowsExceptionClass implements Answer<Object>, Serializable {
+
+ private Class<? extends Throwable> throwableClass;
+ private final ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
+
+ public ThrowsExceptionClass(Class<? extends Throwable> throwableClass) {
+
+ this.throwableClass = throwableClass;
+ }
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+
+ Throwable throwable = (Throwable) ObjenesisHelper.newInstance(throwableClass);
+ throwable.fillInStackTrace();
+ filter.filter(throwable);
+ throw throwable;
+ }
+
+ public Class<? extends Throwable> getThrowableClass() {
+ return throwableClass;
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/answers/package.html b/src/org/mockito/internal/stubbing/answers/package.html
new file mode 100644
index 0000000..3fdeb8d
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/answers/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Answers for stubbed calls
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/Answers.java b/src/org/mockito/internal/stubbing/defaultanswers/Answers.java
new file mode 100644
index 0000000..bf2ff6b
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/Answers.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.mockito.Mockito;
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Enumeration of pre-configured mock answers
+ * <p>
+ * @deprecated - please use Answers from top Mockito package: {@link org.mockito.Answers}
+ * <p>
+ * <b>WARNING</b> Those answers no longer are used by the framework!!! Please use {@link org.mockito.Answers}
+ * <p>
+ * See {@link Mockito} for more information.
+ */
+@Deprecated
+public enum Answers {
+
+ RETURNS_DEFAULTS(new GloballyConfiguredAnswer()),
+ RETURNS_SMART_NULLS(new ReturnsSmartNulls()),
+ RETURNS_MOCKS(new ReturnsMocks()),
+ RETURNS_DEEP_STUBS(new ReturnsDeepStubs()),
+ CALLS_REAL_METHODS(new CallsRealMethods())
+ ;
+
+ private Answer<Object> implementation;
+
+ private Answers(Answer<Object> implementation) {
+ this.implementation = implementation;
+ }
+
+ public Answer<Object> get() {
+ return implementation;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java b/src/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java
new file mode 100644
index 0000000..b3cd3e8
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+/**
+ * Internal answer to forward invocations on a real instance.
+ *
+ * @since 1.9.5
+ */
+public class ForwardsInvocations implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = -8343690268123254910L;
+
+ private Object delegatedObject = null ;
+
+ public ForwardsInvocations(Object delegatedObject) {
+ this.delegatedObject = delegatedObject ;
+ }
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Method method = invocation.getMethod() ;
+
+ return method.invoke(delegatedObject, invocation.getArguments());
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java b/src/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java
new file mode 100644
index 0000000..8e80750
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import java.io.Serializable;
+
+import org.mockito.configuration.IMockitoConfiguration;
+import org.mockito.internal.configuration.GlobalConfiguration;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Globally configured Answer.
+ * <p>
+ * See javadoc for {@link IMockitoConfiguration}
+ */
+public class GloballyConfiguredAnswer implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = 3585893470101750917L;
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return new GlobalConfiguration().getDefaultAnswer().answer(invocation);
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java
new file mode 100644
index 0000000..b08af1b
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.mockito.MockSettings;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.MockitoCore;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.stubbing.InvocationContainerImpl;
+import org.mockito.internal.stubbing.StubbedInvocationMatcher;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.reflection.GenericMetadataSupport;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+
+import static org.mockito.Mockito.withSettings;
+
+/**
+ * Returning deep stub implementation.
+ *
+ * Will return previously created mock if the invocation matches.
+ *
+ * <p>Supports nested generic information, with this answer you can write code like this :
+ *
+ * <pre class="code"><code class="java">
+ * interface GenericsNest<K extends Comparable<K> & Cloneable> extends Map<K, Set<Number>> {}
+ *
+ * GenericsNest<?> mock = mock(GenericsNest.class, new ReturnsGenericDeepStubs());
+ * Number number = mock.entrySet().iterator().next().getValue().iterator().next();
+ * </code></pre>
+ * </p>
+ *
+ * @see org.mockito.Mockito#RETURNS_DEEP_STUBS
+ * @see org.mockito.Answers#RETURNS_DEEP_STUBS
+ */
+public class ReturnsDeepStubs implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = -7105341425736035847L;
+
+ private MockitoCore mockitoCore = new MockitoCore();
+ private ReturnsEmptyValues delegate = new ReturnsEmptyValues();
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ GenericMetadataSupport returnTypeGenericMetadata =
+ actualParameterizedType(invocation.getMock()).resolveGenericReturnType(invocation.getMethod());
+
+ Class<?> rawType = returnTypeGenericMetadata.rawType();
+ if (!mockitoCore.isTypeMockable(rawType)) {
+ return delegate.returnValueFor(rawType);
+ }
+
+ return getMock(invocation, returnTypeGenericMetadata);
+ }
+
+ private Object getMock(InvocationOnMock invocation, GenericMetadataSupport returnTypeGenericMetadata) throws Throwable {
+ InternalMockHandler<Object> handler = new MockUtil().getMockHandler(invocation.getMock());
+ InvocationContainerImpl container = (InvocationContainerImpl) handler.getInvocationContainer();
+
+ // matches invocation for verification
+ for (StubbedInvocationMatcher stubbedInvocationMatcher : container.getStubbedInvocations()) {
+ if(container.getInvocationForStubbing().matches(stubbedInvocationMatcher.getInvocation())) {
+ return stubbedInvocationMatcher.answer(invocation);
+ }
+ }
+
+ // deep stub
+ return recordDeepStubMock(createNewDeepStubMock(returnTypeGenericMetadata), container);
+ }
+
+ /**
+ * Creates a mock using the Generics Metadata.
+ *
+ * <li>Finally as we want to mock the actual type, but we want to pass along the contextual generics meta-data
+ * that was resolved for the current return type, for this to happen we associate to the mock an new instance of
+ * {@link ReturnsDeepStubs} answer in which we will store the returned type generic metadata.
+ *
+ * @param returnTypeGenericMetadata The metadata to use to create the new mock.
+ * @return The mock
+ */
+ private Object createNewDeepStubMock(GenericMetadataSupport returnTypeGenericMetadata) {
+ return mockitoCore.mock(
+ returnTypeGenericMetadata.rawType(),
+ withSettingsUsing(returnTypeGenericMetadata)
+ );
+ }
+
+ private MockSettings withSettingsUsing(GenericMetadataSupport returnTypeGenericMetadata) {
+ MockSettings mockSettings =
+ returnTypeGenericMetadata.rawExtraInterfaces().length > 0 ?
+ withSettings().extraInterfaces(returnTypeGenericMetadata.rawExtraInterfaces())
+ : withSettings();
+
+ return mockSettings
+ .defaultAnswer(returnsDeepStubsAnswerUsing(returnTypeGenericMetadata));
+ }
+
+ private ReturnsDeepStubs returnsDeepStubsAnswerUsing(final GenericMetadataSupport returnTypeGenericMetadata) {
+ return new ReturnsDeepStubs() {
+ @Override
+ protected GenericMetadataSupport actualParameterizedType(Object mock) {
+ return returnTypeGenericMetadata;
+ }
+ };
+ }
+
+ private Object recordDeepStubMock(final Object mock, InvocationContainerImpl container) throws Throwable {
+
+ container.addAnswer(new Answer<Object>() {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return mock;
+ }
+ }, false);
+
+ return mock;
+ }
+
+ protected GenericMetadataSupport actualParameterizedType(Object mock) {
+ CreationSettings mockSettings = (CreationSettings) new MockUtil().getMockHandler(mock).getMockSettings();
+ return GenericMetadataSupport.inferFrom(mockSettings.getTypeToMock());
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java
new file mode 100644
index 0000000..87905b6
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.ObjectMethodsGuru;
+import org.mockito.internal.util.Primitives;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.mock.MockName;
+import org.mockito.stubbing.Answer;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * Default answer of every Mockito mock.
+ * <ul>
+ * <li>
+ * Returns appropriate primitive for primitive-returning methods
+ * </li>
+ * <li>
+ * Returns consistent values for primitive wrapper classes (e.g. int-returning method retuns 0 <b>and</b> Integer-returning method returns 0, too)
+ * </li>
+ * <li>
+ * Returns empty collection for collection-returning methods (works for most commonly used collection types)
+ * </li>
+ * <li>
+ * Returns description of mock for toString() method
+ * </li>
+ * <li>
+ * Returns non-zero for Comparable#compareTo(T other) method (see issue 184)
+ * </li>
+ * <li>
+ * Returns null for everything else
+ * </li>
+ * </ul>
+ */
+public class ReturnsEmptyValues implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = 1998191268711234347L;
+ ObjectMethodsGuru methodsGuru = new ObjectMethodsGuru();
+ MockUtil mockUtil = new MockUtil();
+
+ /* (non-Javadoc)
+ * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock)
+ */
+ public Object answer(InvocationOnMock invocation) {
+ if (methodsGuru.isToString(invocation.getMethod())) {
+ Object mock = invocation.getMock();
+ MockName name = mockUtil.getMockName(mock);
+ if (name.isDefault()) {
+ return "Mock for " + mockUtil.getMockSettings(mock).getTypeToMock().getSimpleName() + ", hashCode: " + mock.hashCode();
+ } else {
+ return name.toString();
+ }
+ } else if (methodsGuru.isCompareToMethod(invocation.getMethod())) {
+ //see issue 184.
+ //mocks by default should not return 0 for compareTo because they are not the same. Hence we return 1 (anything but 0 is good).
+ //Only for compareTo() method by the Comparable interface
+ return 1;
+ }
+
+ Class<?> returnType = invocation.getMethod().getReturnType();
+ return returnValueFor(returnType);
+ }
+
+ Object returnValueFor(Class<?> type) {
+ if (Primitives.isPrimitiveOrWrapper(type)) {
+ return Primitives.defaultValueForPrimitiveOrWrapper(type);
+ //new instances are used instead of Collections.emptyList(), etc.
+ //to avoid UnsupportedOperationException if code under test modifies returned collection
+ } else if (type == Collection.class) {
+ return new LinkedList<Object>();
+ } else if (type == Set.class) {
+ return new HashSet<Object>();
+ } else if (type == HashSet.class) {
+ return new HashSet<Object>();
+ } else if (type == SortedSet.class) {
+ return new TreeSet<Object>();
+ } else if (type == TreeSet.class) {
+ return new TreeSet<Object>();
+ } else if (type == LinkedHashSet.class) {
+ return new LinkedHashSet<Object>();
+ } else if (type == List.class) {
+ return new LinkedList<Object>();
+ } else if (type == LinkedList.class) {
+ return new LinkedList<Object>();
+ } else if (type == ArrayList.class) {
+ return new ArrayList<Object>();
+ } else if (type == Map.class) {
+ return new HashMap<Object, Object>();
+ } else if (type == HashMap.class) {
+ return new HashMap<Object, Object>();
+ } else if (type == SortedMap.class) {
+ return new TreeMap<Object, Object>();
+ } else if (type == TreeMap.class) {
+ return new TreeMap<Object, Object>();
+ } else if (type == LinkedHashMap.class) {
+ return new LinkedHashMap<Object, Object>();
+ }
+ // TODO return empty Iterable ; see issue 175
+
+ //Let's not care about the rest of collections.
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java
new file mode 100755
index 0000000..c57c900
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import java.io.Serializable;
+
+import org.mockito.internal.MockitoCore;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.creation.jmock.ClassImposterizer;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class ReturnsMocks implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = -6755257986994634579L;
+ private MockitoCore mockitoCore = new MockitoCore();
+ private Answer<Object> delegate = new ReturnsMoreEmptyValues();
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Object ret = delegate.answer(invocation);
+ if (ret != null) {
+ return ret;
+ }
+
+ return returnValueFor(invocation.getMethod().getReturnType());
+ }
+
+ Object returnValueFor(Class<?> clazz) {
+ if (!mockitoCore.isTypeMockable(clazz)) {
+ return null;
+ }
+
+ return mockitoCore.mock(clazz, new MockSettingsImpl().defaultAnswer(this));
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java
new file mode 100644
index 0000000..194db14
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.stubbing.defaultanswers;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * It's likely this implementation will be used by default by every Mockito 2.0 mock.
+ * <p>
+ * Currently <b>used only</b> by {@link Mockito#RETURNS_SMART_NULLS}
+ * <p>
+ * Current version of Mockito mocks by deafult use {@link ReturnsEmptyValues}
+ * <ul>
+ * <li>
+ * Returns appropriate primitive for primitive-returning methods
+ * </li>
+ * <li>
+ * Returns consistent values for primitive wrapper classes (e.g. int-returning method retuns 0 <b>and</b> Integer-returning method returns 0, too)
+ * </li>
+ * <li>
+ * Returns empty collection for collection-returning methods (works for most commonly used collection types)
+ * </li>
+ * <li>
+ * Returns empty array for array-returning methods
+ * </li>
+ * <li>
+ * Returns "" for String-returning method
+ * </li>
+ * <li>
+ * Returns description of mock for toString() method
+ * </li>
+ * <li>
+ * Returns non-zero for Comparable#compareTo(T other) method (see issue 184)
+ * </li>
+ * <li>
+ * Returns null for everything else
+ * </li>
+ * </ul>
+ */
+public class ReturnsMoreEmptyValues implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = -2816745041482698471L;
+ private Answer<Object> delegate = new ReturnsEmptyValues();
+
+ /* (non-Javadoc)
+ * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock)
+ */
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Object ret = delegate.answer(invocation);
+ if (ret != null) {
+ return ret;
+ }
+
+ Class<?> returnType = invocation.getMethod().getReturnType();
+ return returnValueFor(returnType);
+ }
+
+ Object returnValueFor(Class<?> type) {
+ if (type == String.class) {
+ return "";
+ } else if (type.isArray()) {
+ Class<?> componenetType = type.getComponentType();
+ return Array.newInstance(componenetType, 0);
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java
new file mode 100644
index 0000000..c2462b0
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.stubbing.defaultanswers;
+
+import java.io.Serializable;
+import java.lang.reflect.Modifier;
+
+import org.mockito.Mockito;
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.debugging.LocationImpl;
+import org.mockito.invocation.Location;
+import org.mockito.internal.util.ObjectMethodsGuru;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Optional Answer that can be used with
+ * {@link Mockito#mock(Class, Answer)}
+ * <p>
+ * This implementation can be helpful when working with legacy code. Unstubbed
+ * methods often return null. If your code uses the object returned by an
+ * unstubbed call you get a NullPointerException. This implementation of
+ * Answer returns SmartNulls instead of nulls.
+ * SmartNull gives nicer exception message than NPE because it points out the
+ * line where unstubbed method was called. You just click on the stack trace.
+ * <p>
+ * ReturnsSmartNulls first tries to return ordinary return values (see
+ * {@link ReturnsMoreEmptyValues}) then it tries to return SmartNull. If the
+ * return type is not mockable (e.g. final) then ordinary null is returned.
+ * <p>
+ * ReturnsSmartNulls will be probably the default return values strategy in
+ * Mockito 2.0
+ */
+public class ReturnsSmartNulls implements Answer<Object>, Serializable {
+
+ private static final long serialVersionUID = 7618312406617949441L;
+
+ private final Answer<Object> delegate = new ReturnsMoreEmptyValues();
+
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ Object defaultReturnValue = delegate.answer(invocation);
+ if (defaultReturnValue != null) {
+ return defaultReturnValue;
+ }
+ Class<?> type = invocation.getMethod().getReturnType();
+ if (!type.isPrimitive() && !Modifier.isFinal(type.getModifiers())) {
+ final Location location = new LocationImpl();
+ return Mockito.mock(type, new ThrowsSmartNullPointer(invocation, location));
+ }
+ return null;
+ }
+
+ private static class ThrowsSmartNullPointer implements Answer {
+ private final InvocationOnMock unstubbedInvocation;
+ private final Location location;
+
+ public ThrowsSmartNullPointer(InvocationOnMock unstubbedInvocation, Location location) {
+ this.unstubbedInvocation = unstubbedInvocation;
+ this.location = location;
+ }
+
+ public Object answer(InvocationOnMock currentInvocation) throws Throwable {
+ if (new ObjectMethodsGuru().isToString(currentInvocation.getMethod())) {
+ return "SmartNull returned by this unstubbed method call on a mock:\n" +
+ unstubbedInvocation.toString();
+ }
+
+ new Reporter().smartNullPointerException(unstubbedInvocation.toString(), location);
+ return null;
+ }
+ }
+}
diff --git a/src/org/mockito/internal/stubbing/defaultanswers/package.html b/src/org/mockito/internal/stubbing/defaultanswers/package.html
new file mode 100644
index 0000000..1587715
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/defaultanswers/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Implementations of ReturnValues
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/stubbing/package.html b/src/org/mockito/internal/stubbing/package.html
new file mode 100644
index 0000000..4f6d4e8
--- /dev/null
+++ b/src/org/mockito/internal/stubbing/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Stubbing logic.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/Checks.java b/src/org/mockito/internal/util/Checks.java
new file mode 100644
index 0000000..00ed8a8
--- /dev/null
+++ b/src/org/mockito/internal/util/Checks.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util;
+
+/**
+ * Pre-made preconditions
+ */
+public class Checks {
+
+ public static <T> T checkNotNull(T value, String checkedValue) {
+ if(value == null) {
+ throw new NullPointerException(checkedValue + " should not be null");
+ }
+ return value;
+ }
+
+ public static <T extends Iterable> T checkItemsNotNull(T iterable, String checkedIterable) {
+ checkNotNull(iterable, checkedIterable);
+ for (Object item : iterable) {
+ checkNotNull(item, "item in " + checkedIterable);
+ }
+ return iterable;
+ }
+}
diff --git a/src/org/mockito/internal/util/ConsoleMockitoLogger.java b/src/org/mockito/internal/util/ConsoleMockitoLogger.java
new file mode 100644
index 0000000..80cac5c
--- /dev/null
+++ b/src/org/mockito/internal/util/ConsoleMockitoLogger.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+public class ConsoleMockitoLogger implements MockitoLogger {
+
+ /* (non-Javadoc)
+ * @see org.mockito.internal.util.Logger#print(java.lang.Object)
+ */
+ public void log(Object what) {
+ System.out.println(what);
+ }
+}
diff --git a/src/org/mockito/internal/util/Decamelizer.java b/src/org/mockito/internal/util/Decamelizer.java
new file mode 100644
index 0000000..9bc34be
--- /dev/null
+++ b/src/org/mockito/internal/util/Decamelizer.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Decamelizer {
+
+private static final Pattern CAPS = Pattern.compile("([A-Z\\d][^A-Z\\d]*)");
+
+ public static String decamelizeMatcher(String className) {
+ if (className.length() == 0) {
+ return "<custom argument matcher>";
+ }
+
+ String decamelized = decamelizeClassName(className);
+
+ if (decamelized.length() == 0) {
+ return "<" + className + ">";
+ }
+
+ return "<" + decamelized + ">";
+ }
+
+ private static String decamelizeClassName(String className) {
+ Matcher match = CAPS.matcher(className);
+ StringBuilder deCameled = new StringBuilder();
+ while(match.find()) {
+ if (deCameled.length() == 0) {
+ deCameled.append(match.group());
+ } else {
+ deCameled.append(" ");
+ deCameled.append(match.group().toLowerCase());
+ }
+ }
+ return deCameled.toString();
+ }
+}
diff --git a/src/org/mockito/internal/util/DefaultMockingDetails.java b/src/org/mockito/internal/util/DefaultMockingDetails.java
new file mode 100644
index 0000000..0de3343
--- /dev/null
+++ b/src/org/mockito/internal/util/DefaultMockingDetails.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.mockito.MockingDetails;
+
+/**
+ * Class to inspect any object, and identify whether a particular object is either a mock or a spy. This is
+ * a wrapper for {@link org.mockito.internal.util.MockUtil}.
+ */
+public class DefaultMockingDetails implements MockingDetails {
+
+ private Object toInspect;
+ private MockUtil delegate;
+
+ public DefaultMockingDetails(Object toInspect, MockUtil delegate){
+ this.toInspect = toInspect;
+ this.delegate = delegate;
+ }
+ /**
+ * Find out whether the object is a mock.
+ * @return true if the object is a mock or a spy.
+ */
+ public boolean isMock(){
+ return delegate.isMock( toInspect );
+ }
+
+ /**
+ * Find out whether the object is a spy.
+ * @return true if the object is a spy.
+ */
+ public boolean isSpy(){
+ return delegate.isSpy( toInspect );
+ }
+}
+
diff --git a/src/org/mockito/internal/util/MockCreationValidator.java b/src/org/mockito/internal/util/MockCreationValidator.java
new file mode 100644
index 0000000..d3a535a
--- /dev/null
+++ b/src/org/mockito/internal/util/MockCreationValidator.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.util.reflection.Constructors;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+@SuppressWarnings("unchecked")
+public class MockCreationValidator {
+
+ private final MockUtil mockUtil = new MockUtil();
+
+ public void validateType(Class classToMock) {
+ if (!mockUtil.isTypeMockable(classToMock)) {
+ new Reporter().cannotMockFinalClass(classToMock);
+ }
+ }
+
+ public void validateExtraInterfaces(Class classToMock, Collection<Class> extraInterfaces) {
+ if (extraInterfaces == null) {
+ return;
+ }
+
+ for (Class i : extraInterfaces) {
+ if (classToMock == i) {
+ new Reporter().extraInterfacesCannotContainMockedType(classToMock);
+ }
+ }
+ }
+
+ public void validateMockedType(Class classToMock, Object spiedInstance) {
+ if (classToMock == null || spiedInstance == null) {
+ return;
+ }
+ if (!classToMock.equals(spiedInstance.getClass())) {
+ new Reporter().mockedTypeIsInconsistentWithSpiedInstanceType(classToMock, spiedInstance);
+ }
+ }
+
+ public void validateDelegatedInstance(Class classToMock, Object delegatedInstance) {
+ if (classToMock == null || delegatedInstance == null) {
+ return;
+ }
+ if (delegatedInstance.getClass().isAssignableFrom(classToMock)) {
+ new Reporter().mockedTypeIsInconsistentWithDelegatedInstanceType(classToMock, delegatedInstance);
+ }
+ }
+
+ public void validateSerializable(Class classToMock, boolean serializable) {
+ // We can't catch all the errors with this piece of code
+ // Having a **superclass that do not implements Serializable** might fail as well when serialized
+ // Though it might prevent issues when mockito is mocking a class without superclass.
+ if(serializable
+ && !classToMock.isInterface()
+ && !(Serializable.class.isAssignableFrom(classToMock))
+ && Constructors.noArgConstructorOf(classToMock) == null
+ ) {
+ new Reporter().serializableWontWorkForObjectsThatDontImplementSerializable(classToMock);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/MockNameImpl.java b/src/org/mockito/internal/util/MockNameImpl.java
new file mode 100644
index 0000000..d8654f3
--- /dev/null
+++ b/src/org/mockito/internal/util/MockNameImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.mockito.mock.MockName;
+
+import java.io.Serializable;
+
+public class MockNameImpl implements MockName, Serializable {
+
+ private static final long serialVersionUID = 8014974700844306925L;
+ private final String mockName;
+ private boolean defaultName;
+
+ @SuppressWarnings("unchecked")
+ public MockNameImpl(String mockName, Class classToMock) {
+ if (mockName == null) {
+ this.mockName = toInstanceName(classToMock);
+ this.defaultName = true;
+ } else {
+ this.mockName = mockName;
+ }
+ }
+
+ public MockNameImpl(String mockName) {
+ this.mockName = mockName;
+ }
+
+ private static String toInstanceName(Class<?> clazz) {
+ String className = clazz.getSimpleName();
+ if (className.length() == 0) {
+ //it's an anonymous class, let's get name from the parent
+ className = clazz.getSuperclass().getSimpleName();
+ }
+ //lower case first letter
+ return className.substring(0, 1).toLowerCase() + className.substring(1);
+ }
+
+ public boolean isDefault() {
+ return defaultName;
+ }
+
+ @Override
+ public String toString() {
+ return mockName;
+ }
+}
diff --git a/src/org/mockito/internal/util/MockUtil.java b/src/org/mockito/internal/util/MockUtil.java
new file mode 100644
index 0000000..e62b3d6
--- /dev/null
+++ b/src/org/mockito/internal/util/MockUtil.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.configuration.ClassPathLoader;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.handler.MockHandlerFactory;
+import org.mockito.internal.util.reflection.LenientCopyTool;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.MockName;
+import org.mockito.plugins.MockMaker;
+
+import java.lang.reflect.Modifier;
+
+@SuppressWarnings("unchecked")
+public class MockUtil {
+
+ private static final MockMaker mockMaker = ClassPathLoader.getMockMaker();
+
+ public boolean isTypeMockable(Class<?> type) {
+ return !type.isPrimitive() && !Modifier.isFinal(type.getModifiers());
+ }
+
+ public <T> T createMock(MockCreationSettings<T> settings) {
+ MockHandler mockHandler = new MockHandlerFactory().create(settings);
+
+ T mock = mockMaker.createMock(settings, mockHandler);
+
+ Object spiedInstance = settings.getSpiedInstance();
+ if (spiedInstance != null) {
+ new LenientCopyTool().copyToMock(spiedInstance, mock);
+ }
+
+ return mock;
+ }
+
+ public <T> void resetMock(T mock) {
+ InternalMockHandler oldHandler = (InternalMockHandler) getMockHandler(mock);
+ MockCreationSettings settings = oldHandler.getMockSettings();
+ MockHandler newHandler = new MockHandlerFactory().create(settings);
+
+ mockMaker.resetMock(mock, newHandler, settings);
+ }
+
+ public <T> InternalMockHandler<T> getMockHandler(T mock) {
+ if (mock == null) {
+ throw new NotAMockException("Argument should be a mock, but is null!");
+ }
+
+ if (isMockitoMock(mock)) {
+ return (InternalMockHandler) mockMaker.getHandler(mock);
+ } else {
+ throw new NotAMockException("Argument should be a mock, but is: " + mock.getClass());
+ }
+ }
+
+ public boolean isMock(Object mock) {
+ // double check to avoid classes that have the same interfaces, could be great to have a custom mockito field in the proxy instead of relying on instance fields
+ return mock instanceof MockitoMock && isMockitoMock(mock);
+ }
+
+ public boolean isSpy(Object mock) {
+ return mock instanceof MockitoSpy;
+ }
+
+ public boolean isMock(Class mockClass) {
+ return mockClass != null && MockitoMock.class.isAssignableFrom(mockClass);
+ }
+
+ public boolean isSpy(Class mockClass) {
+ return mockClass != null && MockitoSpy.class.isAssignableFrom(mockClass);
+ }
+
+ private <T> boolean isMockitoMock(T mock) {
+ return mockMaker.getHandler(mock) != null;
+ }
+
+ public MockName getMockName(Object mock) {
+ return getMockHandler(mock).getMockSettings().getMockName();
+ }
+
+ public void maybeRedefineMockName(Object mock, String newName) {
+ MockName mockName = getMockName(mock);
+ //TODO SF hacky...
+ if (mockName.isDefault() && getMockHandler(mock).getMockSettings() instanceof CreationSettings) {
+ ((CreationSettings) getMockHandler(mock).getMockSettings()).setMockName(new MockNameImpl(newName));
+ }
+ }
+
+ public MockCreationSettings getMockSettings(Object mock) {
+ return getMockHandler(mock).getMockSettings();
+ }
+}
diff --git a/src/org/mockito/internal/util/MockitoLogger.java b/src/org/mockito/internal/util/MockitoLogger.java
new file mode 100644
index 0000000..31117d8
--- /dev/null
+++ b/src/org/mockito/internal/util/MockitoLogger.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+public interface MockitoLogger {
+
+ void log(Object what);
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/MockitoMock.java b/src/org/mockito/internal/util/MockitoMock.java
new file mode 100644
index 0000000..05f1d51
--- /dev/null
+++ b/src/org/mockito/internal/util/MockitoMock.java
@@ -0,0 +1,9 @@
+package org.mockito.internal.util;
+
+/**
+ * Mark internally a Mockito mock.
+ *
+ * To be used un conjunction with {@link MockUtil#isMock(Object)}
+ */
+public interface MockitoMock {
+}
diff --git a/src/org/mockito/internal/util/MockitoSpy.java b/src/org/mockito/internal/util/MockitoSpy.java
new file mode 100644
index 0000000..30d8362
--- /dev/null
+++ b/src/org/mockito/internal/util/MockitoSpy.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+/**
+ * Mark internally a Mockito spy.
+ *
+ * To be used un conjunction with {@link MockUtil#isMock(Object)} or {@link MockUtil#isSpy(Object)}.
+ */
+public interface MockitoSpy extends MockitoMock {
+}
diff --git a/src/org/mockito/internal/util/ObjectMethodsGuru.java b/src/org/mockito/internal/util/ObjectMethodsGuru.java
new file mode 100644
index 0000000..4e78249
--- /dev/null
+++ b/src/org/mockito/internal/util/ObjectMethodsGuru.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import org.mockito.internal.creation.DelegatingMethod;
+import org.mockito.internal.invocation.MockitoMethod;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+public class ObjectMethodsGuru implements Serializable {
+
+ private static final long serialVersionUID = -1286718569065470494L;
+
+ public boolean isToString(Method method) {
+ return isToString(new DelegatingMethod(method));
+ }
+
+ public boolean isToString(MockitoMethod method) {
+ return method.getReturnType() == String.class
+ && method.getParameterTypes().length == 0
+ && method.getName().equals("toString");
+ }
+
+ public boolean isEqualsMethod(Method method) {
+ return method.getName().equals("equals")
+ && method.getParameterTypes().length == 1
+ && method.getParameterTypes()[0] == Object.class;
+ }
+
+ public boolean isHashCodeMethod(Method method) {
+ return method.getName().equals("hashCode")
+ && method.getParameterTypes().length == 0;
+ }
+
+ public boolean isCompareToMethod(Method method) {
+ return Comparable.class.isAssignableFrom(method.getDeclaringClass())
+ && method.getName().equals("compareTo")
+ && method.getParameterTypes().length == 1
+ && method.getParameterTypes()[0] == method.getDeclaringClass();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/Primitives.java b/src/org/mockito/internal/util/Primitives.java
new file mode 100644
index 0000000..9b444cf
--- /dev/null
+++ b/src/org/mockito/internal/util/Primitives.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SuppressWarnings("unchecked")
+public class Primitives {
+
+ private static Map<Class<?>, Class<?>> primitiveTypes = new HashMap<Class<?>, Class<?>>();
+ private static Map<Class<?>, Object> primitiveOrWrapperDefaultValues = new HashMap<Class<?>, Object>();
+
+
+ /**
+ * Returns the primitive type of the given class.
+ * <p/>
+ * The passed class can be any class : <code>boolean.class</code>, <code>Integer.class</code>
+ * in witch case this method will return <code>boolean.class</code>, even <code>SomeObject.class</code>
+ * in which case <code>null</code> will be returned.
+ *
+ * @param clazz The class from which primitive type has to be retrieved
+ * @param <T> The type
+ * @return The primitive type if relevant, otherwise <code>null</code>
+ */
+ public static <T> Class<T> primitiveTypeOf(Class<T> clazz) {
+ if (clazz.isPrimitive()) {
+ return clazz;
+ }
+ return (Class<T>) primitiveTypes.get(clazz);
+ }
+
+ /**
+ * Indicates if the given class is primitive type or a primitive wrapper.
+ *
+ * @param type The type to check
+ * @return <code>true</code> if primitive or wrapper, <code>false</code> otherwise.
+ */
+ public static boolean isPrimitiveOrWrapper(Class<?> type) {
+ return primitiveOrWrapperDefaultValues.containsKey(type);
+ }
+
+ /**
+ * Returns the boxed default value for a primitive or a primitive wrapper.
+ *
+ * @param primitiveOrWrapperType The type to lookup the default value
+ * @return The boxed default values as defined in Java Language Specification,
+ * <code>null</code> if the type is neither a primitive nor a wrapper
+ */
+ public static <T> T defaultValueForPrimitiveOrWrapper(Class<T> primitiveOrWrapperType) {
+ return (T) primitiveOrWrapperDefaultValues.get(primitiveOrWrapperType);
+ }
+
+
+ static {
+ primitiveTypes.put(Boolean.class, Boolean.TYPE);
+ primitiveTypes.put(Character.class, Character.TYPE);
+ primitiveTypes.put(Byte.class, Byte.TYPE);
+ primitiveTypes.put(Short.class, Short.TYPE);
+ primitiveTypes.put(Integer.class, Integer.TYPE);
+ primitiveTypes.put(Long.class, Long.TYPE);
+ primitiveTypes.put(Float.class, Float.TYPE);
+ primitiveTypes.put(Double.class, Double.TYPE);
+ }
+
+ static {
+ primitiveOrWrapperDefaultValues.put(Boolean.class, false);
+ primitiveOrWrapperDefaultValues.put(Character.class, '\u0000');
+ primitiveOrWrapperDefaultValues.put(Byte.class, (byte) 0);
+ primitiveOrWrapperDefaultValues.put(Short.class, (short) 0);
+ primitiveOrWrapperDefaultValues.put(Integer.class, 0);
+ primitiveOrWrapperDefaultValues.put(Long.class, 0L);
+ primitiveOrWrapperDefaultValues.put(Float.class, 0F);
+ primitiveOrWrapperDefaultValues.put(Double.class, 0D);
+
+ primitiveOrWrapperDefaultValues.put(boolean.class, false);
+ primitiveOrWrapperDefaultValues.put(char.class, '\u0000');
+ primitiveOrWrapperDefaultValues.put(byte.class, (byte) 0);
+ primitiveOrWrapperDefaultValues.put(short.class, (short) 0);
+ primitiveOrWrapperDefaultValues.put(int.class, 0);
+ primitiveOrWrapperDefaultValues.put(long.class, 0L);
+ primitiveOrWrapperDefaultValues.put(float.class, 0F);
+ primitiveOrWrapperDefaultValues.put(double.class, 0D);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/RemoveFirstLine.java b/src/org/mockito/internal/util/RemoveFirstLine.java
new file mode 100644
index 0000000..517f88f
--- /dev/null
+++ b/src/org/mockito/internal/util/RemoveFirstLine.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+public class RemoveFirstLine {
+
+ /**
+ * @param text to have the first line removed
+ * @return less first line
+ */
+ public String of(String text) {
+ return text.replaceFirst(".*?\n", "");
+ }
+}
diff --git a/src/org/mockito/internal/util/SimpleMockitoLogger.java b/src/org/mockito/internal/util/SimpleMockitoLogger.java
new file mode 100644
index 0000000..6ee40ea
--- /dev/null
+++ b/src/org/mockito/internal/util/SimpleMockitoLogger.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util;
+
+public class SimpleMockitoLogger extends ConsoleMockitoLogger {
+
+ StringBuilder loggedInfo = new StringBuilder();
+
+ public void log(Object what) {
+// can be uncommented when debugging this test
+// super.log(what);
+ loggedInfo.append(what);
+ }
+
+ public String getLoggedInfo() {
+ return loggedInfo.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/StringJoiner.java b/src/org/mockito/internal/util/StringJoiner.java
new file mode 100644
index 0000000..2cbab0c
--- /dev/null
+++ b/src/org/mockito/internal/util/StringJoiner.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util;
+
+public class StringJoiner {
+
+ public static String join(Object ... linesToBreak) {
+ StringBuilder out = new StringBuilder("\n");
+ return join(out, linesToBreak);
+ }
+
+ private static String join(StringBuilder out, Object[] linesToBreak) {
+ for (Object line : linesToBreak) {
+ out.append(line.toString()).append("\n");
+ }
+ int lastBreak = out.lastIndexOf("\n");
+ return out.replace(lastBreak, lastBreak+1, "").toString();
+ }
+}
diff --git a/src/org/mockito/internal/util/collections/ArrayUtils.java b/src/org/mockito/internal/util/collections/ArrayUtils.java
new file mode 100644
index 0000000..1b3859c
--- /dev/null
+++ b/src/org/mockito/internal/util/collections/ArrayUtils.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.collections;
+
+@SuppressWarnings("unchecked")
+public class ArrayUtils {
+
+ public <T> boolean isEmpty(T[] array) {
+ return array == null || array.length == 0;
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java b/src/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java
new file mode 100644
index 0000000..251c2a0
--- /dev/null
+++ b/src/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.collections;
+
+import org.mockito.internal.util.MockUtil;
+
+/**
+ * hashCode and equals safe mock wrapper.
+ *
+ * <p>
+ * It doesn't use the actual mock {@link Object#hashCode} and {@link Object#equals} method as they might
+ * throw an NPE if those method cannot be stubbed <em>even internally</em>.
+ * </p>
+ *
+ * <p>
+ * Instead the strategy is :
+ * <ul>
+ * <li>For hashCode : <strong>use {@link System#identityHashCode}</strong></li>
+ * <li>For equals : <strong>use the object reference equality</strong></li>
+ * </ul>
+ * </p>
+ *
+ * @see HashCodeAndEqualsSafeSet
+ */
+public class HashCodeAndEqualsMockWrapper {
+
+ private Object mockInstance;
+
+ public HashCodeAndEqualsMockWrapper(Object mockInstance) {
+ this.mockInstance = mockInstance;
+ }
+
+ public Object get() {
+ return mockInstance;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof HashCodeAndEqualsMockWrapper)) return false;
+
+ HashCodeAndEqualsMockWrapper that = (HashCodeAndEqualsMockWrapper) o;
+
+ return mockInstance == that.mockInstance;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(mockInstance);
+ }
+
+ public static HashCodeAndEqualsMockWrapper of(Object mock) {
+ return new HashCodeAndEqualsMockWrapper(mock);
+ }
+
+ @Override public String toString() {
+ MockUtil mockUtil = new MockUtil();
+ return "HashCodeAndEqualsMockWrapper{" +
+ "mockInstance=" + (mockUtil.isMock(mockInstance) ? mockUtil.getMockName(mockInstance) : typeInstanceString()) +
+ '}';
+ }
+
+ private String typeInstanceString() {
+ return mockInstance.getClass().getSimpleName() + "(" + System.identityHashCode(mockInstance) + ")";
+ }
+}
diff --git a/src/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java b/src/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java
new file mode 100644
index 0000000..d9c82cf
--- /dev/null
+++ b/src/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.collections;
+
+import org.mockito.internal.util.Checks;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static java.lang.reflect.Array.*;
+
+/**
+ * hashCode and equals safe hash based set.
+ *
+ * <p>
+ * Useful for holding mocks that have un-stubbable hashCode or equals method,
+ * meaning that in this scenario the real code is always called and will most probably
+ * cause an {@link NullPointerException}.
+ * </p>
+ * <p>
+ * This collection wraps the mock in an augmented type {@link HashCodeAndEqualsMockWrapper}
+ * that have his own implementation.
+ * </p>
+ *
+ * @see HashCodeAndEqualsMockWrapper
+ */
+public class HashCodeAndEqualsSafeSet implements Set<Object> {
+
+ private HashSet<HashCodeAndEqualsMockWrapper> backingHashSet = new HashSet<HashCodeAndEqualsMockWrapper>();
+
+ public Iterator<Object> iterator() {
+ return new Iterator<Object>() {
+ private Iterator<HashCodeAndEqualsMockWrapper> iterator = backingHashSet.iterator();
+
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ public Object next() {
+ return iterator.next().get();
+ }
+
+ public void remove() {
+ iterator.remove();
+ }
+ };
+ }
+
+ public int size() {
+ return backingHashSet.size();
+ }
+
+ public boolean isEmpty() {
+ return backingHashSet.isEmpty();
+ }
+
+ public boolean contains(Object mock) {
+ return backingHashSet.contains(HashCodeAndEqualsMockWrapper.of(mock));
+ }
+
+ public boolean add(Object mock) {
+ return backingHashSet.add(HashCodeAndEqualsMockWrapper.of(mock));
+ }
+
+ public boolean remove(Object mock) {
+ return backingHashSet.remove(HashCodeAndEqualsMockWrapper.of(mock));
+ }
+
+ public void clear() {
+ backingHashSet.clear();
+ }
+
+ @Override public Object clone() throws CloneNotSupportedException {
+ throw new CloneNotSupportedException();
+ }
+
+ @Override public boolean equals(Object o) {
+ if (!(o instanceof HashCodeAndEqualsSafeSet)) {
+ return false;
+ }
+ HashCodeAndEqualsSafeSet that = (HashCodeAndEqualsSafeSet) o;
+ return backingHashSet.equals(that.backingHashSet);
+ }
+
+ @Override public int hashCode() {
+ return backingHashSet.hashCode();
+ }
+
+ public Object[] toArray() {
+ return unwrapTo(new Object[size()]);
+ }
+
+ private <T> T[] unwrapTo(T[] array) {
+ Iterator<Object> iterator = iterator();
+ for (int i = 0, objectsLength = array.length; i < objectsLength; i++) {
+ if (iterator.hasNext()) {
+ array[i] = (T) iterator.next();
+ }
+ }
+ return array;
+ }
+
+
+ public <T> T[] toArray(T[] typedArray) {
+ T[] array = typedArray.length >= size() ? typedArray :
+ (T[]) newInstance(typedArray.getClass().getComponentType(), size());
+ return unwrapTo(array);
+ }
+
+ public boolean removeAll(Collection<?> mocks) {
+ return backingHashSet.removeAll(asWrappedMocks(mocks));
+ }
+
+ public boolean containsAll(Collection<?> mocks) {
+ return backingHashSet.containsAll(asWrappedMocks(mocks));
+ }
+
+ public boolean addAll(Collection<?> mocks) {
+ return backingHashSet.addAll(asWrappedMocks(mocks));
+ }
+
+ public boolean retainAll(Collection<?> mocks) {
+ return backingHashSet.retainAll(asWrappedMocks(mocks));
+ }
+
+ private HashSet<HashCodeAndEqualsMockWrapper> asWrappedMocks(Collection<?> mocks) {
+ Checks.checkNotNull(mocks, "Passed collection should notify() be null");
+ HashSet<HashCodeAndEqualsMockWrapper> hashSet = new HashSet<HashCodeAndEqualsMockWrapper>();
+ for (Object mock : mocks) {
+ assert ! (mock instanceof HashCodeAndEqualsMockWrapper) : "WRONG";
+ hashSet.add(HashCodeAndEqualsMockWrapper.of(mock));
+ }
+ return hashSet;
+ }
+
+ @Override public String toString() {
+ return backingHashSet.toString();
+ }
+
+ public static HashCodeAndEqualsSafeSet of(Object... mocks) {
+ return of(Arrays.asList(mocks));
+ }
+
+ public static HashCodeAndEqualsSafeSet of(Iterable<Object> objects) {
+ HashCodeAndEqualsSafeSet hashCodeAndEqualsSafeSet = new HashCodeAndEqualsSafeSet();
+ if (objects != null) {
+ for (Object mock : objects) {
+ hashCodeAndEqualsSafeSet.add(mock);
+ }
+ }
+ return hashCodeAndEqualsSafeSet;
+ }
+}
diff --git a/src/org/mockito/internal/util/collections/IdentitySet.java b/src/org/mockito/internal/util/collections/IdentitySet.java
new file mode 100644
index 0000000..661d609
--- /dev/null
+++ b/src/org/mockito/internal/util/collections/IdentitySet.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.collections;
+
+import java.util.LinkedList;
+
+@SuppressWarnings("unchecked")
+public class IdentitySet {
+
+ LinkedList list = new LinkedList();
+
+ public boolean contains(Object o) {
+ for(Object existing:list) {
+ if (existing == o) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void add(Object o) {
+ list.add(o);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/collections/ListUtil.java b/src/org/mockito/internal/util/collections/ListUtil.java
new file mode 100644
index 0000000..6b492c6
--- /dev/null
+++ b/src/org/mockito/internal/util/collections/ListUtil.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util.collections;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+public class ListUtil {
+
+ public static <T> LinkedList<T> filter(Collection<T> collection, Filter<T> filter) {
+ LinkedList<T> filtered = new LinkedList<T>();
+ for (T t : collection) {
+ if (!filter.isOut(t)) {
+ filtered.add(t);
+ }
+ }
+ return filtered;
+ }
+
+ public static interface Filter<T> {
+ boolean isOut(T object);
+ }
+}
diff --git a/src/org/mockito/internal/util/collections/Sets.java b/src/org/mockito/internal/util/collections/Sets.java
new file mode 100644
index 0000000..6095549
--- /dev/null
+++ b/src/org/mockito/internal/util/collections/Sets.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.collections;
+
+
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+
+public abstract class Sets {
+ public static Set<Object> newMockSafeHashSet(Iterable<Object> mocks) {
+ return HashCodeAndEqualsSafeSet.of(mocks);
+ }
+
+ public static Set<Object> newMockSafeHashSet(Object... mocks) {
+ return HashCodeAndEqualsSafeSet.of(mocks);
+ }
+
+ public static IdentitySet newIdentitySet() {
+ return new IdentitySet();
+ }
+
+ public static <T> Set<T> newSet(T ... elements) {
+ if (elements == null) {
+ throw new IllegalArgumentException("Expected an array of elements (or empty array) but received a null.");
+ }
+ return new LinkedHashSet<T>(asList(elements));
+ }
+}
diff --git a/src/org/mockito/internal/util/junit/JUnitFailureHacker.java b/src/org/mockito/internal/util/junit/JUnitFailureHacker.java
new file mode 100644
index 0000000..debc871
--- /dev/null
+++ b/src/org/mockito/internal/util/junit/JUnitFailureHacker.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.junit;
+
+import org.junit.runner.notification.Failure;
+import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings;
+import org.mockito.internal.util.reflection.Whitebox;
+
+public class JUnitFailureHacker {
+
+ public void appendWarnings(Failure failure, String warnings) {
+ if (isEmpty(warnings)) {
+ return;
+ }
+ //TODO: this has to protect the use in case jUnit changes and this internal state logic fails
+ Throwable throwable = (Throwable) Whitebox.getInternalState(failure, "fThrownException");
+
+ String newMessage = "contains both: actual test failure *and* Mockito warnings.\n" +
+ warnings + "\n *** The actual failure is because of: ***\n";
+
+ ExceptionIncludingMockitoWarnings e = new ExceptionIncludingMockitoWarnings(newMessage, throwable);
+ e.setStackTrace(throwable.getStackTrace());
+ Whitebox.setInternalState(failure, "fThrownException", e);
+ }
+
+ private boolean isEmpty(String warnings) {
+ return warnings == null || "".equals(warnings); // isEmpty() is in JDK 6+
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/package.html b/src/org/mockito/internal/util/package.html
new file mode 100644
index 0000000..b86ca1c
--- /dev/null
+++ b/src/org/mockito/internal/util/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Static utils
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/reflection/AccessibilityChanger.java b/src/org/mockito/internal/util/reflection/AccessibilityChanger.java
new file mode 100644
index 0000000..a1d59c3
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/AccessibilityChanger.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.AccessibleObject;
+
+public class AccessibilityChanger {
+
+ private Boolean wasAccessible = null;
+
+ /**
+ * safely disables access
+ */
+ public void safelyDisableAccess(AccessibleObject accessibleObject) {
+ assert wasAccessible != null : "accessibility info shall not be null";
+ try {
+ accessibleObject.setAccessible(wasAccessible);
+ } catch (Throwable t) {
+ //ignore
+ }
+ }
+
+ /**
+ * changes the accessibleObject accessibility and returns true if accessibility was changed
+ */
+ public void enableAccess(AccessibleObject accessibleObject) {
+ wasAccessible = accessibleObject.isAccessible();
+ accessibleObject.setAccessible(true);
+ }
+}
diff --git a/src/org/mockito/internal/util/reflection/BeanPropertySetter.java b/src/org/mockito/internal/util/reflection/BeanPropertySetter.java
new file mode 100644
index 0000000..d84d57a
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/BeanPropertySetter.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+/**
+ * This utility class will call the setter of the property to inject a new value.
+ */
+public class BeanPropertySetter {
+
+ private static final String SET_PREFIX = "set";
+
+ private final Object target;
+ private boolean reportNoSetterFound;
+ private final Field field;
+
+ /**
+ * New BeanPropertySetter
+ * @param target The target on which the setter must be invoked
+ * @param propertyField The field that should be accessed with the setter
+ * @param reportNoSetterFound Allow the set method to raise an Exception if the setter cannot be found
+ */
+ public BeanPropertySetter(final Object target, final Field propertyField, boolean reportNoSetterFound) {
+ this.field = propertyField;
+ this.target = target;
+ this.reportNoSetterFound = reportNoSetterFound;
+ }
+
+ /**
+ * New BeanPropertySetter that don't report failure
+ * @param target The target on which the setter must be invoked
+ * @param propertyField The propertyField that must be accessed through a setter
+ */
+ public BeanPropertySetter(final Object target, final Field propertyField) {
+ this(target, propertyField, false);
+ }
+
+ /**
+ * Set the value to the property represented by this {@link BeanPropertySetter}
+ * @param value the new value to pass to the property setter
+ * @return <code>true</code> if the value has been injected, <code>false</code> otherwise
+ * @throws RuntimeException Can be thrown if the setter threw an exception, if the setter is not accessible
+ * or, if <code>reportNoSetterFound</code> and setter could not be found.
+ */
+ public boolean set(final Object value) {
+
+ AccessibilityChanger changer = new AccessibilityChanger();
+ Method writeMethod = null;
+ try {
+ writeMethod = target.getClass().getMethod(setterName(field.getName()), field.getType());
+
+ changer.enableAccess(writeMethod);
+ writeMethod.invoke(target, value);
+ return true;
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException("Setter '" + writeMethod + "' of '" + target + "' with value '" + value + "' threw exception : '" + e.getTargetException() + "'", e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Access not authorized on field '" + field + "' of object '" + target + "' with value: '" + value + "'", e);
+ } catch (NoSuchMethodException e) {
+ reportNoSetterFound();
+ } finally {
+ if(writeMethod != null) {
+ changer.safelyDisableAccess(writeMethod);
+ }
+ }
+
+ reportNoSetterFound();
+ return false;
+ }
+
+ /**
+ * Retrieve the setter name from the field name.
+ *
+ * <p>Implementation is based on the code of {@link java.beans.Introspector}.</p>
+ *
+ * @param fieldName the Field name
+ * @return Setter name.
+ */
+ private String setterName(String fieldName) {
+ return new StringBuilder(SET_PREFIX)
+ .append(fieldName.substring(0, 1).toUpperCase(Locale.ENGLISH))
+ .append(fieldName.substring(1))
+ .toString();
+ }
+
+ private void reportNoSetterFound() {
+ if(reportNoSetterFound) {
+ throw new RuntimeException("Problems setting value on object: [" + target + "] for property : [" + field.getName() + "], setter not found");
+ }
+ }
+
+}
diff --git a/src/org/mockito/internal/util/reflection/Constructors.java b/src/org/mockito/internal/util/reflection/Constructors.java
new file mode 100644
index 0000000..909de8c
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/Constructors.java
@@ -0,0 +1,20 @@
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Constructor;
+
+public abstract class Constructors {
+
+ /**
+ * Returns the no arg constructor of the type if any.
+ *
+ * @param classToMock The type to look for a no-arg constructor
+ * @return The no-arg constructor or null if none is declared.
+ */
+ public static Constructor<?> noArgConstructorOf(Class<?> classToMock) {
+ try {
+ return classToMock.getDeclaredConstructor();
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+}
diff --git a/src/org/mockito/internal/util/reflection/FieldCopier.java b/src/org/mockito/internal/util/reflection/FieldCopier.java
new file mode 100644
index 0000000..bc6bcff
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/FieldCopier.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+
+public class FieldCopier {
+
+ public <T> void copyValue(T from, T to, Field field) throws IllegalAccessException {
+ Object value = field.get(from);
+ field.set(to, value);
+ }
+}
diff --git a/src/org/mockito/internal/util/reflection/FieldInitializationReport.java b/src/org/mockito/internal/util/reflection/FieldInitializationReport.java
new file mode 100644
index 0000000..ffe2afd
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/FieldInitializationReport.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.util.reflection;
+
+/**
+ * Report on field initialization
+ */
+public class FieldInitializationReport {
+ private Object fieldInstance;
+ private boolean wasInitialized;
+ private boolean wasInitializedUsingConstructorArgs;
+
+ public FieldInitializationReport(Object fieldInstance, boolean wasInitialized, boolean wasInitializedUsingConstructorArgs) {
+ this.fieldInstance = fieldInstance;
+ this.wasInitialized = wasInitialized;
+ this.wasInitializedUsingConstructorArgs = wasInitializedUsingConstructorArgs;
+ }
+
+ /**
+ * Returns the actual field instance.
+ *
+ * @return the actual instance
+ */
+ public Object fieldInstance() {
+ return fieldInstance;
+ }
+
+ /**
+ * Indicate wether the field was created during the process or not.
+ *
+ * @return <code>true</code> if created, <code>false</code> if the field did already hold an instance.
+ */
+ public boolean fieldWasInitialized() {
+ return wasInitialized;
+ }
+
+ /**
+ * Indicate wether the field was created using constructor args.
+ *
+ * @return <code>true</code> if field was created using constructor parameters.
+ */
+ public boolean fieldWasInitializedUsingContructorArgs() {
+ return wasInitializedUsingConstructorArgs;
+ }
+
+ /**
+ * Returns the class of the actual instance in the field.
+ *
+ * @return Class of the instance
+ */
+ public Class<?> fieldClass() {
+ return fieldInstance != null ? fieldInstance.getClass() : null;
+ }
+}
+
diff --git a/src/org/mockito/internal/util/reflection/FieldInitializer.java b/src/org/mockito/internal/util/reflection/FieldInitializer.java
new file mode 100644
index 0000000..a6d2d44
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/FieldInitializer.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.mockito.exceptions.base.MockitoException;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Initialize a field with type instance if a default constructor can be found.
+ *
+ * <p>
+ * If the given field is already initialized, then <strong>the actual instance is returned</strong>.
+ * This initializer doesn't work with inner classes, local classes, interfaces or abstract types.
+ * </p>
+ *
+ */
+public class FieldInitializer {
+
+ private Object fieldOwner;
+ private Field field;
+ private ConstructorInstantiator instantiator;
+
+
+ /**
+ * Prepare initializer with the given field on the given instance.
+ *
+ * <p>
+ * This constructor fail fast if the field type cannot be handled.
+ * </p>
+ *
+ * @param fieldOwner Instance of the test.
+ * @param field Field to be initialize.
+ */
+ public FieldInitializer(Object fieldOwner, Field field) {
+ this(fieldOwner, field, new NoArgConstructorInstantiator(fieldOwner, field));
+ }
+
+ /**
+ * Prepare initializer with the given field on the given instance.
+ *
+ * <p>
+ * This constructor fail fast if the field type cannot be handled.
+ * </p>
+ *
+ * @param fieldOwner Instance of the test.
+ * @param field Field to be initialize.
+ * @param argResolver Constructor parameters resolver
+ */
+ public FieldInitializer(Object fieldOwner, Field field, ConstructorArgumentResolver argResolver) {
+ this(fieldOwner, field, new ParameterizedConstructorInstantiator(fieldOwner, field, argResolver));
+ }
+
+ private FieldInitializer(Object fieldOwner, Field field, ConstructorInstantiator instantiator) {
+ if(new FieldReader(fieldOwner, field).isNull()) {
+ checkNotLocal(field);
+ checkNotInner(field);
+ checkNotInterface(field);
+ checkNotAbstract(field);
+ }
+ this.fieldOwner = fieldOwner;
+ this.field = field;
+ this.instantiator = instantiator;
+ }
+
+ /**
+ * Initialize field if not initialized and return the actual instance.
+ *
+ * @return Actual field instance.
+ */
+ public FieldInitializationReport initialize() {
+ final AccessibilityChanger changer = new AccessibilityChanger();
+ changer.enableAccess(field);
+
+ try {
+ return acquireFieldInstance();
+ } catch(IllegalAccessException e) {
+ throw new MockitoException("Problems initializing field '" + field.getName() + "' of type '" + field.getType().getSimpleName() + "'", e);
+ } finally {
+ changer.safelyDisableAccess(field);
+ }
+ }
+
+ private void checkNotLocal(Field field) {
+ if(field.getType().isLocalClass()) {
+ throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is a local class.");
+ }
+ }
+
+ private void checkNotInner(Field field) {
+ if(field.getType().isMemberClass() && !Modifier.isStatic(field.getType().getModifiers())) {
+ throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is an inner class.");
+ }
+ }
+
+ private void checkNotInterface(Field field) {
+ if(field.getType().isInterface()) {
+ throw new MockitoException("the type '" + field.getType().getSimpleName() + "' is an interface.");
+ }
+ }
+
+ private void checkNotAbstract(Field field) {
+ if(Modifier.isAbstract(field.getType().getModifiers())) {
+ throw new MockitoException("the type '" + field.getType().getSimpleName() + " is an abstract class.");
+ }
+ }
+
+ private FieldInitializationReport acquireFieldInstance() throws IllegalAccessException {
+ Object fieldInstance = field.get(fieldOwner);
+ if(fieldInstance != null) {
+ return new FieldInitializationReport(fieldInstance, false, false);
+ }
+
+ return instantiator.instantiate();
+ }
+
+ /**
+ * Represents the strategy used to resolve actual instances
+ * to be given to a constructor given the argument types.
+ */
+ public interface ConstructorArgumentResolver {
+
+ /**
+ * Try to resolve instances from types.
+ *
+ * <p>
+ * Checks on the real argument type or on the correct argument number
+ * will happen during the field initialization {@link FieldInitializer#initialize()}.
+ * I.e the only responsibility of this method, is to provide instances <strong>if possible</strong>.
+ * </p>
+ *
+ * @param argTypes Constructor argument types, should not be null.
+ * @return The argument instances to be given to the constructor, should not be null.
+ */
+ Object[] resolveTypeInstances(Class<?>... argTypes);
+ }
+
+ private interface ConstructorInstantiator {
+ FieldInitializationReport instantiate();
+ }
+
+ /**
+ * Constructor instantiating strategy for no-arg constructor.
+ *
+ * <p>
+ * If a no-arg constructor can be found then the instance is created using
+ * this constructor.
+ * Otherwise a technical MockitoException is thrown.
+ * </p>
+ */
+ static class NoArgConstructorInstantiator implements ConstructorInstantiator {
+ private Object testClass;
+ private Field field;
+
+ /**
+ * Internal, checks are done by FieldInitializer.
+ * Fields are assumed to be accessible.
+ */
+ NoArgConstructorInstantiator(Object testClass, Field field) {
+ this.testClass = testClass;
+ this.field = field;
+ }
+
+ public FieldInitializationReport instantiate() {
+ final AccessibilityChanger changer = new AccessibilityChanger();
+ Constructor<?> constructor = null;
+ try {
+ constructor = field.getType().getDeclaredConstructor();
+ changer.enableAccess(constructor);
+
+ final Object[] noArg = new Object[0];
+ Object newFieldInstance = constructor.newInstance(noArg);
+ new FieldSetter(testClass, field).set(newFieldInstance);
+
+ return new FieldInitializationReport(field.get(testClass), true, false);
+ } catch (NoSuchMethodException e) {
+ throw new MockitoException("the type '" + field.getType().getSimpleName() + "' has no default constructor", e);
+ } catch (InvocationTargetException e) {
+ throw new MockitoException("the default constructor of type '" + field.getType().getSimpleName() + "' has raised an exception (see the stack trace for cause): " + e.getTargetException().toString(), e);
+ } catch (InstantiationException e) {
+ throw new MockitoException("InstantiationException (see the stack trace for cause): " + e.toString(), e);
+ } catch (IllegalAccessException e) {
+ throw new MockitoException("IllegalAccessException (see the stack trace for cause): " + e.toString(), e);
+ } finally {
+ if(constructor != null) {
+ changer.safelyDisableAccess(constructor);
+ }
+ }
+ }
+ }
+
+ /**
+ * Constructor instantiating strategy for parameterized constructors.
+ *
+ * <p>
+ * Choose the constructor with the highest number of parameters, then
+ * call the ConstructorArgResolver to get actual argument instances.
+ * If the argResolver fail, then a technical MockitoException is thrown is thrown.
+ * Otherwise the instance is created with the resolved arguments.
+ * </p>
+ */
+ static class ParameterizedConstructorInstantiator implements ConstructorInstantiator {
+ private Object testClass;
+ private Field field;
+ private ConstructorArgumentResolver argResolver;
+ private Comparator<Constructor<?>> byParameterNumber = new Comparator<Constructor<?>>() {
+ public int compare(Constructor<?> constructorA, Constructor<?> constructorB) {
+ return constructorB.getParameterTypes().length - constructorA.getParameterTypes().length;
+ }
+ };
+
+ /**
+ * Internal, checks are done by FieldInitializer.
+ * Fields are assumed to be accessible.
+ */
+ ParameterizedConstructorInstantiator(Object testClass, Field field, ConstructorArgumentResolver argumentResolver) {
+ this.testClass = testClass;
+ this.field = field;
+ this.argResolver = argumentResolver;
+ }
+
+ public FieldInitializationReport instantiate() {
+ final AccessibilityChanger changer = new AccessibilityChanger();
+ Constructor<?> constructor = null;
+ try {
+ constructor = biggestConstructor(field.getType());
+ changer.enableAccess(constructor);
+
+ final Object[] args = argResolver.resolveTypeInstances(constructor.getParameterTypes());
+ Object newFieldInstance = constructor.newInstance(args);
+ new FieldSetter(testClass, field).set(newFieldInstance);
+
+ return new FieldInitializationReport(field.get(testClass), false, true);
+ } catch (IllegalArgumentException e) {
+ throw new MockitoException("internal error : argResolver provided incorrect types for constructor " + constructor + " of type " + field.getType().getSimpleName(), e);
+ } catch (InvocationTargetException e) {
+ throw new MockitoException("the constructor of type '" + field.getType().getSimpleName() + "' has raised an exception (see the stack trace for cause): " + e.getTargetException().toString(), e);
+ } catch (InstantiationException e) {
+ throw new MockitoException("InstantiationException (see the stack trace for cause): " + e.toString(), e);
+ } catch (IllegalAccessException e) {
+ throw new MockitoException("IllegalAccessException (see the stack trace for cause): " + e.toString(), e);
+ } finally {
+ if(constructor != null) {
+ changer.safelyDisableAccess(constructor);
+ }
+ }
+ }
+
+ private void checkParameterized(Constructor<?> constructor, Field field) {
+ if(constructor.getParameterTypes().length == 0) {
+ throw new MockitoException("the field " + field.getName() + " of type " + field.getType() + " has no parameterized constructor");
+ }
+ }
+
+ private Constructor<?> biggestConstructor(Class<?> clazz) {
+ final List<Constructor<?>> constructors = Arrays.asList(clazz.getDeclaredConstructors());
+ Collections.sort(constructors, byParameterNumber);
+
+ Constructor<?> constructor = constructors.get(0);
+ checkParameterized(constructor, field);
+ return constructor;
+ }
+ }
+}
diff --git a/src/org/mockito/internal/util/reflection/FieldReader.java b/src/org/mockito/internal/util/reflection/FieldReader.java
new file mode 100644
index 0000000..49a62e7
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/FieldReader.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.mockito.exceptions.base.MockitoException;
+
+import java.lang.reflect.Field;
+
+public class FieldReader {
+
+ final Object target;
+ final Field field;
+ final AccessibilityChanger changer = new AccessibilityChanger();
+
+ public FieldReader(Object target, Field field) {
+ this.target = target;
+ this.field = field;
+ changer.enableAccess(field);
+ }
+
+ public boolean isNull() {
+ return read() == null;
+ }
+
+ public Object read() {
+ try {
+ return field.get(target);
+ } catch (Exception e) {
+ throw new MockitoException("Cannot read state from field: " + field + ", on instance: " + target);
+ }
+ }
+}
diff --git a/src/org/mockito/internal/util/reflection/FieldSetter.java b/src/org/mockito/internal/util/reflection/FieldSetter.java
new file mode 100644
index 0000000..5972767
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/FieldSetter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+
+public class FieldSetter {
+
+ private final Object target;
+ private final Field field;
+
+ public FieldSetter(Object target, Field field) {
+ this.target = target;
+ this.field = field;
+ }
+
+ public void set(Object value) {
+ AccessibilityChanger changer = new AccessibilityChanger();
+ changer.enableAccess(field);
+ try {
+ field.set(target, value);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Access not authorized on field '" + field + "' of object '" + target + "' with value: '" + value + "'", e);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Wrong argument on field '" + field + "' of object '" + target + "' with value: '" + value + "', \n" +
+ "reason : " + e.getMessage(), e);
+ }
+ changer.safelyDisableAccess(field);
+ }
+}
diff --git a/src/org/mockito/internal/util/reflection/Fields.java b/src/org/mockito/internal/util/reflection/Fields.java
new file mode 100644
index 0000000..024dc9b
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/Fields.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.mockito.Incubating;
+import org.mockito.internal.util.Checks;
+import org.mockito.internal.util.collections.ListUtil.Filter;
+import org.mockito.internal.util.collections.ListUtil;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Small fluent reflection tools to work with fields.
+ *
+ * Code is very new and might need rework.
+ */
+@Incubating
+public abstract class Fields {
+
+ /**
+ * Instance fields declared in the class and superclasses of the given instance.
+ *
+ * @param instance Instance from which declared fields will be retrieved.
+ * @return InstanceFields of this object instance.
+ */
+ public static InstanceFields allDeclaredFieldsOf(Object instance) {
+ List<InstanceField> instanceFields = new ArrayList<InstanceField>();
+ for (Class<?> clazz = instance.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
+ instanceFields.addAll(instanceFieldsIn(instance, clazz.getDeclaredFields()));
+ }
+ return new InstanceFields(instance, instanceFields);
+ }
+
+ /**
+ * Instance fields declared in the class of the given instance.
+ *
+ * @param instance Instance from which declared fields will be retrieved.
+ * @return InstanceFields of this object instance.
+ */
+ public static InstanceFields declaredFieldsOf(Object instance) {
+ List<InstanceField> instanceFields = new ArrayList<InstanceField>();
+ instanceFields.addAll(instanceFieldsIn(instance, instance.getClass().getDeclaredFields()));
+ return new InstanceFields(instance, instanceFields);
+ }
+
+ private static List<InstanceField> instanceFieldsIn(Object instance, Field[] fields) {
+ List<InstanceField> instanceDeclaredFields = new ArrayList<InstanceField>();
+ for (Field field : fields) {
+ InstanceField instanceField = new InstanceField(field, instance);
+ instanceDeclaredFields.add(instanceField);
+ }
+ return instanceDeclaredFields;
+ }
+
+ /**
+ * Accept fields annotated by the given annotations.
+ *
+ * @param annotations Annotation types to check.
+ * @return The filter.
+ */
+ public static Filter<InstanceField> annotatedBy(final Class<? extends Annotation>... annotations) {
+ return new Filter<InstanceField>() {
+ public boolean isOut(InstanceField instanceField) {
+ Checks.checkNotNull(annotations, "Provide at least one annotation class");
+
+ for (Class<? extends Annotation> annotation : annotations) {
+ if(instanceField.isAnnotatedBy(annotation)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+ }
+
+ /**
+ * Accept fields with non null value.
+ *
+ * @return The filter.
+ */
+ private static Filter<InstanceField> nullField() {
+ return new Filter<InstanceField>() {
+ public boolean isOut(InstanceField instanceField) {
+ return instanceField.isNull();
+ }
+ };
+ }
+
+ public static class InstanceFields {
+ private final Object instance;
+
+ private final List<InstanceField> instanceFields;
+
+ public InstanceFields(Object instance, List<InstanceField> instanceFields) {
+ this.instance = instance;
+ this.instanceFields = instanceFields;
+ }
+
+ public InstanceFields filter(Filter<InstanceField> withFilter) {
+ return new InstanceFields(instance, ListUtil.filter(instanceFields, withFilter));
+ }
+
+ public InstanceFields notNull() {
+ return filter(nullField());
+ }
+
+ public List<InstanceField> instanceFields() {
+ return new ArrayList<InstanceField>(instanceFields);
+ }
+
+ public List<Object> assignedValues() {
+ List<Object> values = new ArrayList<Object>(instanceFields.size());
+ for (InstanceField instanceField : instanceFields) {
+ values.add(instanceField.read());
+ }
+ return values;
+ }
+
+ public List<String> names() {
+ List<String> fieldNames = new ArrayList<String>(instanceFields.size());
+ for (InstanceField instanceField : instanceFields) {
+ fieldNames.add(instanceField.name());
+ }
+ return fieldNames;
+ }
+ }
+}
diff --git a/src/org/mockito/internal/util/reflection/GenericMaster.java b/src/org/mockito/internal/util/reflection/GenericMaster.java
new file mode 100644
index 0000000..29e384a
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/GenericMaster.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+@SuppressWarnings("unchecked")
+public class GenericMaster {
+
+ /**
+ * Finds the generic type (parametrized type) of the field. If the field is not generic it returns Object.class.
+ *
+ * @param field
+ */
+ public Class getGenericType(Field field) {
+ Type generic = field.getGenericType();
+ if (generic != null && generic instanceof ParameterizedType) {
+ Type actual = ((ParameterizedType) generic).getActualTypeArguments()[0];
+ if (actual instanceof Class) {
+ return (Class) actual;
+ } else if (actual instanceof ParameterizedType) {
+ //in case of nested generics we don't go deep
+ return (Class) ((ParameterizedType) actual).getRawType();
+ }
+ }
+
+ return Object.class;
+ }
+
+}
diff --git a/src/org/mockito/internal/util/reflection/GenericMetadataSupport.java b/src/org/mockito/internal/util/reflection/GenericMetadataSupport.java
new file mode 100644
index 0000000..6cea091
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/GenericMetadataSupport.java
@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+
+import org.mockito.Incubating;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.util.Checks;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+
+/**
+ * This class can retrieve generic meta-data that the compiler stores on classes
+ * and accessible members.
+ *
+ * <p>
+ * The main idea of this code is to create a Map that will help to resolve return types.
+ * In order to actually work with nested generics, this map will have to be passed along new instances
+ * as a type context.
+ * </p>
+ *
+ * <p>
+ * Hence :
+ * <ul>
+ * <li>A new instance representing the metadata is created using the {@link #inferFrom(Type)} method from a real
+ * <code>Class</code> or from a <code>ParameterizedType</code>, other types are not yet supported.</li>
+ *
+ * <li>Then from this metadata, we can extract meta-data for a generic return type of a method, using
+ * {@link #resolveGenericReturnType(Method)}.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * For now this code support the following kind of generic declarations :
+ * <pre class="code"><code class="java">
+ * interface GenericsNest<K extends Comparable<K> & Cloneable> extends Map<K, Set<Number>> {
+ * Set<Number> remove(Object key); // override with fixed ParameterizedType
+ * List<? super Integer> returning_wildcard_with_class_lower_bound();
+ * List<? super K> returning_wildcard_with_typeVar_lower_bound();
+ * List<? extends K> returning_wildcard_with_typeVar_upper_bound();
+ * K returningK();
+ * <O extends K> List<O> paramType_with_type_params();
+ * <S, T extends S> T two_type_params();
+ * <O extends K> O typeVar_with_type_params();
+ * Number returningNonGeneric();
+ * }
+ * </code></pre>
+ *
+ * @see #inferFrom(Type)
+ * @see #resolveGenericReturnType(Method)
+ * @see org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs
+ */
+@Incubating
+public abstract class GenericMetadataSupport {
+
+ // public static MockitoLogger logger = new ConsoleMockitoLogger();
+
+ /**
+ * Represents actual type variables resolved for current class.
+ */
+ protected Map<TypeVariable, Type> contextualActualTypeParameters = new HashMap<TypeVariable, Type>();
+
+
+ protected void registerTypeVariablesOn(Type classType) {
+ if (!(classType instanceof ParameterizedType)) {
+ return;
+ }
+ ParameterizedType parameterizedType = (ParameterizedType) classType;
+ TypeVariable[] typeParameters = ((Class<?>) parameterizedType.getRawType()).getTypeParameters();
+ Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+ for (int i = 0; i < actualTypeArguments.length; i++) {
+ TypeVariable typeParameter = typeParameters[i];
+ Type actualTypeArgument = actualTypeArguments[i];
+
+ if (actualTypeArgument instanceof WildcardType) {
+ contextualActualTypeParameters.put(typeParameter, boundsOf((WildcardType) actualTypeArgument));
+ } else {
+ contextualActualTypeParameters.put(typeParameter, actualTypeArgument);
+ }
+ // logger.log("For '" + parameterizedType + "' found type variable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualTypeArgument + "(" + System.identityHashCode(typeParameter) + ")" + "' }");
+ }
+ }
+
+ protected void registerTypeParametersOn(TypeVariable[] typeParameters) {
+ for (TypeVariable typeParameter : typeParameters) {
+ contextualActualTypeParameters.put(typeParameter, boundsOf(typeParameter));
+ // logger.log("For '" + typeParameter.getGenericDeclaration() + "' found type variable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + boundsOf(typeParameter) + "' }");
+ }
+ }
+
+ /**
+ * @param typeParameter The TypeVariable parameter
+ * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable
+ * then retrieve BoundedType of this TypeVariable
+ */
+ private BoundedType boundsOf(TypeVariable typeParameter) {
+ if (typeParameter.getBounds()[0] instanceof TypeVariable) {
+ return boundsOf((TypeVariable) typeParameter.getBounds()[0]);
+ }
+ return new TypeVarBoundedType(typeParameter);
+ }
+
+ /**
+ * @param wildCard The WildCard type
+ * @return A {@link BoundedType} for easy bound information, if first bound is a TypeVariable
+ * then retrieve BoundedType of this TypeVariable
+ */
+ private BoundedType boundsOf(WildcardType wildCard) {
+ /*
+ * According to JLS(http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1):
+ * - Lower and upper can't coexist: (for instance, this is not allowed: <? extends List<String> & super MyInterface>)
+ * - Multiple bounds are not supported (for instance, this is not allowed: <? extends List<String> & MyInterface>)
+ */
+
+ WildCardBoundedType wildCardBoundedType = new WildCardBoundedType(wildCard);
+ if (wildCardBoundedType.firstBound() instanceof TypeVariable) {
+ return boundsOf((TypeVariable) wildCardBoundedType.firstBound());
+ }
+
+ return wildCardBoundedType;
+ }
+
+
+
+ /**
+ * @return Raw type of the current instance.
+ */
+ public abstract Class<?> rawType();
+
+
+
+ /**
+ * @return Returns extra interfaces <strong>if relevant</strong>, otherwise empty List.
+ */
+ public List<Type> extraInterfaces() {
+ return Collections.emptyList();
+ }
+
+ /**
+ * @return Returns an array with the raw types of {@link #extraInterfaces()} <strong>if relevant</strong>.
+ */
+ public Class<?>[] rawExtraInterfaces() {
+ return new Class[0];
+ }
+
+
+
+ /**
+ * @return Actual type arguments matching the type variables of the raw type represented by this {@link GenericMetadataSupport} instance.
+ */
+ public Map<TypeVariable, Type> actualTypeArguments() {
+ TypeVariable[] typeParameters = rawType().getTypeParameters();
+ LinkedHashMap<TypeVariable, Type> actualTypeArguments = new LinkedHashMap<TypeVariable, Type>();
+
+ for (TypeVariable typeParameter : typeParameters) {
+
+ Type actualType = getActualTypeArgumentFor(typeParameter);
+
+ actualTypeArguments.put(typeParameter, actualType);
+ // logger.log("For '" + rawType().getCanonicalName() + "' returning explicit TypeVariable : { '" + typeParameter + "(" + System.identityHashCode(typeParameter) + ")" + "' : '" + actualType +"' }");
+ }
+
+ return actualTypeArguments;
+ }
+
+ protected Type getActualTypeArgumentFor(TypeVariable typeParameter) {
+ Type type = this.contextualActualTypeParameters.get(typeParameter);
+ if (type instanceof TypeVariable) {
+ TypeVariable typeVariable = (TypeVariable) type;
+ return getActualTypeArgumentFor(typeVariable);
+ }
+
+ return type;
+ }
+
+
+
+ /**
+ * Resolve current method generic return type to a {@link GenericMetadataSupport}.
+ *
+ * @param method Method to resolve the return type.
+ * @return {@link GenericMetadataSupport} representing this generic return type.
+ */
+ public GenericMetadataSupport resolveGenericReturnType(Method method) {
+ Type genericReturnType = method.getGenericReturnType();
+ // logger.log("Method '" + method.toGenericString() + "' has return type : " + genericReturnType.getClass().getInterfaces()[0].getSimpleName() + " : " + genericReturnType);
+
+ if (genericReturnType instanceof Class) {
+ return new NotGenericReturnTypeSupport(genericReturnType);
+ }
+ if (genericReturnType instanceof ParameterizedType) {
+ return new ParameterizedReturnType(this, method.getTypeParameters(), (ParameterizedType) method.getGenericReturnType());
+ }
+ if (genericReturnType instanceof TypeVariable) {
+ return new TypeVariableReturnType(this, method.getTypeParameters(), (TypeVariable) genericReturnType);
+ }
+
+ throw new MockitoException("Ouch, it shouldn't happen, type '" + genericReturnType.getClass().getCanonicalName() + "' on method : '" + method.toGenericString() + "' is not supported : " + genericReturnType);
+ }
+
+ /**
+ * Create an new instance of {@link GenericMetadataSupport} inferred from a {@link Type}.
+ *
+ * <p>
+ * At the moment <code>type</code> can only be a {@link Class} or a {@link ParameterizedType}, otherwise
+ * it'll throw a {@link MockitoException}.
+ * </p>
+ *
+ * @param type The class from which the {@link GenericMetadataSupport} should be built.
+ * @return The new {@link GenericMetadataSupport}.
+ * @throws MockitoException Raised if type is not a {@link Class} or a {@link ParameterizedType}.
+ */
+ public static GenericMetadataSupport inferFrom(Type type) {
+ Checks.checkNotNull(type, "type");
+ if (type instanceof Class) {
+ return new FromClassGenericMetadataSupport((Class<?>) type);
+ }
+ if (type instanceof ParameterizedType) {
+ return new FromParameterizedTypeGenericMetadataSupport((ParameterizedType) type);
+ }
+
+ throw new MockitoException("Type meta-data for this Type (" + type.getClass().getCanonicalName() + ") is not supported : " + type);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //// Below are specializations of GenericMetadataSupport that could handle retrieval of possible Types
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Generic metadata implementation for {@link Class}.
+ *
+ * Offer support to retrieve generic metadata on a {@link Class} by reading type parameters and type variables on
+ * the class and its ancestors and interfaces.
+ */
+ private static class FromClassGenericMetadataSupport extends GenericMetadataSupport {
+ private Class<?> clazz;
+
+ public FromClassGenericMetadataSupport(Class<?> clazz) {
+ this.clazz = clazz;
+ readActualTypeParametersOnDeclaringClass();
+ }
+
+ private void readActualTypeParametersOnDeclaringClass() {
+ registerTypeParametersOn(clazz.getTypeParameters());
+ registerTypeVariablesOn(clazz.getGenericSuperclass());
+ for (Type genericInterface : clazz.getGenericInterfaces()) {
+ registerTypeVariablesOn(genericInterface);
+ }
+ }
+
+ @Override
+ public Class<?> rawType() {
+ return clazz;
+ }
+ }
+
+
+ /**
+ * Generic metadata implementation for "standalone" {@link ParameterizedType}.
+ *
+ * Offer support to retrieve generic metadata on a {@link ParameterizedType} by reading type variables of
+ * the related raw type and declared type variable of this parameterized type.
+ *
+ * This class is not designed to work on ParameterizedType returned by {@link Method#getGenericReturnType()}, as
+ * the ParameterizedType instance return in these cases could have Type Variables that refer to type declaration(s).
+ * That's what meant the "standalone" word at the beginning of the Javadoc.
+ * Instead use {@link ParameterizedReturnType}.
+ */
+ private static class FromParameterizedTypeGenericMetadataSupport extends GenericMetadataSupport {
+ private ParameterizedType parameterizedType;
+
+ public FromParameterizedTypeGenericMetadataSupport(ParameterizedType parameterizedType) {
+ this.parameterizedType = parameterizedType;
+ readActualTypeParameters();
+ }
+
+ private void readActualTypeParameters() {
+ registerTypeVariablesOn(parameterizedType.getRawType());
+ registerTypeVariablesOn(parameterizedType);
+ }
+
+ @Override
+ public Class<?> rawType() {
+ return (Class<?>) parameterizedType.getRawType();
+ }
+ }
+
+
+ /**
+ * Generic metadata specific to {@link ParameterizedType} returned via {@link Method#getGenericReturnType()}.
+ */
+ private static class ParameterizedReturnType extends GenericMetadataSupport {
+ private final ParameterizedType parameterizedType;
+ private final TypeVariable[] typeParameters;
+
+ public ParameterizedReturnType(GenericMetadataSupport source, TypeVariable[] typeParameters, ParameterizedType parameterizedType) {
+ this.parameterizedType = parameterizedType;
+ this.typeParameters = typeParameters;
+ this.contextualActualTypeParameters = source.contextualActualTypeParameters;
+
+ readTypeParameters();
+ readTypeVariables();
+ }
+
+ private void readTypeParameters() {
+ registerTypeParametersOn(typeParameters);
+ }
+
+ private void readTypeVariables() {
+ registerTypeVariablesOn(parameterizedType);
+ }
+
+ @Override
+ public Class<?> rawType() {
+ return (Class<?>) parameterizedType.getRawType();
+ }
+
+ }
+
+
+ /**
+ * Generic metadata for {@link TypeVariable} returned via {@link Method#getGenericReturnType()}.
+ */
+ private static class TypeVariableReturnType extends GenericMetadataSupport {
+ private final TypeVariable typeVariable;
+ private final TypeVariable[] typeParameters;
+ private Class<?> rawType;
+
+
+
+ public TypeVariableReturnType(GenericMetadataSupport source, TypeVariable[] typeParameters, TypeVariable typeVariable) {
+ this.typeParameters = typeParameters;
+ this.typeVariable = typeVariable;
+ this.contextualActualTypeParameters = source.contextualActualTypeParameters;
+
+ readTypeParameters();
+ readTypeVariables();
+ }
+
+ private void readTypeParameters() {
+ registerTypeParametersOn(typeParameters);
+ }
+
+ private void readTypeVariables() {
+ for (Type type : typeVariable.getBounds()) {
+ registerTypeVariablesOn(type);
+ }
+ registerTypeVariablesOn(getActualTypeArgumentFor(typeVariable));
+ }
+
+ @Override
+ public Class<?> rawType() {
+ if (rawType == null) {
+ rawType = extractRawTypeOf(typeVariable);
+ }
+ return rawType;
+ }
+
+ private Class<?> extractRawTypeOf(Type type) {
+ if (type instanceof Class) {
+ return (Class<?>) type;
+ }
+ if (type instanceof ParameterizedType) {
+ return (Class<?>) ((ParameterizedType) type).getRawType();
+ }
+ if (type instanceof BoundedType) {
+ return extractRawTypeOf(((BoundedType) type).firstBound());
+ }
+ if (type instanceof TypeVariable) {
+ /*
+ * If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared
+ * on the class definition, such as such as List<E>.
+ */
+ return extractRawTypeOf(contextualActualTypeParameters.get(type));
+ }
+ throw new MockitoException("Raw extraction not supported for : '" + type + "'");
+ }
+
+ @Override
+ public List<Type> extraInterfaces() {
+ Type type = extractActualBoundedTypeOf(typeVariable);
+ if (type instanceof BoundedType) {
+ return Arrays.asList(((BoundedType) type).interfaceBounds());
+ }
+ if (type instanceof ParameterizedType) {
+ return Collections.singletonList(type);
+ }
+ if (type instanceof Class) {
+ return Collections.emptyList();
+ }
+ throw new MockitoException("Cannot extract extra-interfaces from '" + typeVariable + "' : '" + type + "'");
+ }
+
+ /**
+ * @return Returns an array with the extracted raw types of {@link #extraInterfaces()}.
+ * @see #extractRawTypeOf(java.lang.reflect.Type)
+ */
+ public Class<?>[] rawExtraInterfaces() {
+ List<Type> extraInterfaces = extraInterfaces();
+ List<Class<?>> rawExtraInterfaces = new ArrayList<Class<?>>();
+ for (Type extraInterface : extraInterfaces) {
+ Class<?> rawInterface = extractRawTypeOf(extraInterface);
+ // avoid interface collision with actual raw type (with typevariables, resolution ca be quite aggressive)
+ if(!rawType().equals(rawInterface)) {
+ rawExtraInterfaces.add(rawInterface);
+ }
+ }
+ return rawExtraInterfaces.toArray(new Class[rawExtraInterfaces.size()]);
+ }
+
+ private Type extractActualBoundedTypeOf(Type type) {
+ if (type instanceof TypeVariable) {
+ /*
+ If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared
+ on the class definition, such as such as List<E>.
+ */
+ return extractActualBoundedTypeOf(contextualActualTypeParameters.get(type));
+ }
+ if (type instanceof BoundedType) {
+ Type actualFirstBound = extractActualBoundedTypeOf(((BoundedType) type).firstBound());
+ if (!(actualFirstBound instanceof BoundedType)) {
+ return type; // avoid going one step further, ie avoid : O(TypeVar) -> K(TypeVar) -> Some ParamType
+ }
+ return actualFirstBound;
+ }
+ return type; // irrelevant, we don't manage other types as they are not bounded.
+ }
+ }
+
+
+
+ /**
+ * Non-Generic metadata for {@link Class} returned via {@link Method#getGenericReturnType()}.
+ */
+ private static class NotGenericReturnTypeSupport extends GenericMetadataSupport {
+ private final Class<?> returnType;
+
+ public NotGenericReturnTypeSupport(Type genericReturnType) {
+ returnType = (Class<?>) genericReturnType;
+ }
+
+ @Override
+ public Class<?> rawType() {
+ return returnType;
+ }
+ }
+
+
+
+ /**
+ * Type representing bounds of a type
+ *
+ * @see TypeVarBoundedType
+ * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>
+ * @see WildCardBoundedType
+ * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.5.1</a>
+ */
+ public static interface BoundedType extends Type {
+ Type firstBound();
+
+ Type[] interfaceBounds();
+ }
+
+ /**
+ * Type representing bounds of a type variable, allows to keep all bounds information.
+ *
+ * <p>It uses the first bound in the array, as this array is never null and always contains at least
+ * one element (Object is always here if no bounds are declared).</p>
+ *
+ * <p>If upper bounds are declared with SomeClass and additional interfaces, then firstBound will be SomeClass and
+ * interfacesBound will be an array of the additional interfaces.
+ *
+ * i.e. <code>SomeClass</code>.
+ * <pre class="code"><code class="java">
+ * interface UpperBoundedTypeWithClass<E extends Comparable<E> & Cloneable> {
+ * E get();
+ * }
+ * // will return Comparable type
+ * </code></pre>
+ * </p>
+ *
+ * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>
+ */
+ public static class TypeVarBoundedType implements BoundedType {
+ private TypeVariable typeVariable;
+
+
+ public TypeVarBoundedType(TypeVariable typeVariable) {
+ this.typeVariable = typeVariable;
+ }
+
+ /**
+ * @return either a class or an interface (parameterized or not), if no bounds declared Object is returned.
+ */
+ public Type firstBound() {
+ return typeVariable.getBounds()[0]; //
+ }
+
+ /**
+ * On a Type Variable (typeVar extends C_0 & I_1 & I_2 & etc), will return an array
+ * containing I_1 and I_2.
+ *
+ * @return other bounds for this type, these bounds can only be only interfaces as the JLS says,
+ * empty array if no other bound declared.
+ */
+ public Type[] interfaceBounds() {
+ Type[] interfaceBounds = new Type[typeVariable.getBounds().length - 1];
+ System.arraycopy(typeVariable.getBounds(), 1, interfaceBounds, 0, typeVariable.getBounds().length - 1);
+ return interfaceBounds;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ return typeVariable.equals(((TypeVarBoundedType) o).typeVariable);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return typeVariable.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("{firstBound=").append(firstBound());
+ sb.append(", interfaceBounds=").append(Arrays.deepToString(interfaceBounds()));
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public TypeVariable typeVariable() {
+ return typeVariable;
+ }
+ }
+
+ /**
+ * Type representing bounds of a wildcard, allows to keep all bounds information.
+ *
+ * <p>The JLS says that lower bound and upper bound are mutually exclusive, and that multiple bounds
+ * are not allowed.
+ *
+ * @see <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.4</a>
+ */
+ public static class WildCardBoundedType implements BoundedType {
+ private WildcardType wildcard;
+
+
+ public WildCardBoundedType(WildcardType wildcard) {
+ this.wildcard = wildcard;
+ }
+
+ /**
+ * @return The first bound, either a type or a reference to a TypeVariable
+ */
+ public Type firstBound() {
+ Type[] lowerBounds = wildcard.getLowerBounds();
+ Type[] upperBounds = wildcard.getUpperBounds();
+
+ return lowerBounds.length != 0 ? lowerBounds[0] : upperBounds[0];
+ }
+
+ /**
+ * @return An empty array as, wildcard don't support multiple bounds.
+ */
+ public Type[] interfaceBounds() {
+ return new Type[0];
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ return wildcard.equals(((TypeVarBoundedType) o).typeVariable);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return wildcard.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("{firstBound=").append(firstBound());
+ sb.append(", interfaceBounds=[]}");
+ return sb.toString();
+ }
+
+ public WildcardType wildCard() {
+ return wildcard;
+ }
+ }
+
+}
+
+
diff --git a/src/org/mockito/internal/util/reflection/InstanceField.java b/src/org/mockito/internal/util/reflection/InstanceField.java
new file mode 100644
index 0000000..9e64e19
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/InstanceField.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import org.mockito.internal.util.Checks;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+/**
+ * Represents an accessible instance field.
+ *
+ * Contains the instance reference on which the field can be read adn write.
+ */
+public class InstanceField {
+ private final Field field;
+ private final Object instance;
+ private FieldReader fieldReader;
+
+ /**
+ * Create a new InstanceField.
+ *
+ * @param field The field that should be accessed, note that no checks are performed to ensure
+ * the field belong to this instance class.
+ * @param instance The instance from which the field shall be accessed.
+ */
+ public InstanceField(Field field, Object instance) {
+ this.field = Checks.checkNotNull(field, "field");
+ this.instance = Checks.checkNotNull(instance, "instance");
+ }
+
+ /**
+ * Safely read the field.
+ *
+ * @return the field value.
+ * @see FieldReader
+ */
+ public Object read() {
+ return reader().read();
+ }
+
+ /**
+ * Set the given value to the field of this instance.
+ *
+ * @param value The value that should be written to the field.
+ * @see FieldSetter
+ */
+ public void set(Object value) {
+ new FieldSetter(instance, field).set(value);
+ }
+
+ /**
+ * Check that the field is not null.
+ *
+ * @return <code>true</code> if <code>null</code>, else <code>false</code>.
+ */
+ public boolean isNull() {
+ return reader().isNull();
+ }
+
+ /**
+ * Check if the field is annotated by the given annotation.
+ *
+ * @param annotationClass The annotation type to check.
+ * @return <code>true</code> if the field is annotated by this annotation, else <code>false</code>.
+ */
+ public boolean isAnnotatedBy(Class<? extends Annotation> annotationClass) {
+ return field.isAnnotationPresent(annotationClass);
+ }
+
+ /**
+ * Returns the annotation instance for the given annotation type.
+ *
+ * @param annotationClass Tha annotation type to retrieve.
+ * @param <A> Type of the annotation.
+ * @return The annotation instance.
+ */
+ public <A extends Annotation> A annotation(Class<A> annotationClass) {
+ return field.getAnnotation(annotationClass);
+ }
+
+ /**
+ * Returns the JDK {@link Field} instance.
+ *
+ * @return The actual {@link Field} instance.
+ */
+ public Field jdkField() {
+ return field;
+ }
+
+ private FieldReader reader() {
+ if (fieldReader == null) {
+ fieldReader = new FieldReader(instance, field);
+ }
+ return fieldReader;
+ }
+
+ /**
+ * Returns the name of the field.
+ *
+ * @return Name of the field.
+ */
+ public String name() {
+ return field.getName();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ InstanceField that = (InstanceField) o;
+
+ if (!field.equals(that.field)) return false;
+ if (!instance.equals(that.instance)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = field.hashCode();
+ result = 31 * result + instance.hashCode();
+ return result;
+ }
+}
diff --git a/src/org/mockito/internal/util/reflection/LenientCopyTool.java b/src/org/mockito/internal/util/reflection/LenientCopyTool.java
new file mode 100644
index 0000000..2418ced
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/LenientCopyTool.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+@SuppressWarnings("unchecked")
+public class LenientCopyTool {
+
+ FieldCopier fieldCopier = new FieldCopier();
+
+ public <T> void copyToMock(T from, T mock) {
+ copy(from, mock, from.getClass(), mock.getClass().getSuperclass());
+ }
+
+ public <T> void copyToRealObject(T from, T to) {
+ copy(from, to, from.getClass(), to.getClass());
+ }
+
+ private <T> void copy(T from, T to, Class fromClazz, Class toClass) {
+ while (fromClazz != Object.class) {
+ copyValues(from, to, fromClazz);
+ fromClazz = fromClazz.getSuperclass();
+ }
+ }
+
+ private <T> void copyValues(T from, T mock, Class classFrom) {
+ Field[] fields = classFrom.getDeclaredFields();
+
+ for (int i = 0; i < fields.length; i++) {
+ // ignore static fields
+ Field field = fields[i];
+ if (Modifier.isStatic(field.getModifiers())) {
+ continue;
+ }
+ AccessibilityChanger accessibilityChanger = new AccessibilityChanger();
+ try {
+ accessibilityChanger.enableAccess(field);
+ fieldCopier.copyValue(from, mock, field);
+ } catch (Throwable t) {
+ //Ignore - be lenient - if some field cannot be copied then let's be it
+ } finally {
+ accessibilityChanger.safelyDisableAccess(field);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/reflection/Whitebox.java b/src/org/mockito/internal/util/reflection/Whitebox.java
new file mode 100644
index 0000000..d1ba5fd
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/Whitebox.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.util.reflection;
+
+import java.lang.reflect.Field;
+
+public class Whitebox {
+
+ public static Object getInternalState(Object target, String field) {
+ Class<?> c = target.getClass();
+ try {
+ Field f = getFieldFromHierarchy(c, field);
+ f.setAccessible(true);
+ return f.get(target);
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to set internal state on a private field. Please report to mockito mailing list.", e);
+ }
+ }
+
+ public static void setInternalState(Object target, String field, Object value) {
+ Class<?> c = target.getClass();
+ try {
+ Field f = getFieldFromHierarchy(c, field);
+ f.setAccessible(true);
+ f.set(target, value);
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to set internal state on a private field. Please report to mockito mailing list.", e);
+ }
+ }
+
+ private static Field getFieldFromHierarchy(Class<?> clazz, String field) {
+ Field f = getField(clazz, field);
+ while (f == null && clazz != Object.class) {
+ clazz = clazz.getSuperclass();
+ f = getField(clazz, field);
+ }
+ if (f == null) {
+ throw new RuntimeException(
+ "You want me to set value to this field: '" + field +
+ "' on this class: '" + clazz.getSimpleName() +
+ "' but this field is not declared withing hierarchy of this class!");
+ }
+ return f;
+ }
+
+ private static Field getField(Class<?> clazz, String field) {
+ try {
+ return clazz.getDeclaredField(field);
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/util/reflection/package.html b/src/org/mockito/internal/util/reflection/package.html
new file mode 100644
index 0000000..ac2eca0
--- /dev/null
+++ b/src/org/mockito/internal/util/reflection/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+reflection utilities
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/AtLeast.java b/src/org/mockito/internal/verification/AtLeast.java
new file mode 100644
index 0000000..db2cbda
--- /dev/null
+++ b/src/org/mockito/internal/verification/AtLeast.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import java.util.List;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.internal.verification.api.VerificationDataInOrder;
+import org.mockito.internal.verification.api.VerificationInOrderMode;
+import org.mockito.internal.verification.checkers.AtLeastXNumberOfInvocationsChecker;
+import org.mockito.internal.verification.checkers.AtLeastXNumberOfInvocationsInOrderChecker;
+import org.mockito.internal.verification.checkers.MissingInvocationChecker;
+import org.mockito.internal.verification.checkers.MissingInvocationInOrderChecker;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+public class AtLeast implements VerificationInOrderMode, VerificationMode {
+
+ final int wantedCount;
+
+ public AtLeast(int wantedNumberOfInvocations) {
+ if (wantedNumberOfInvocations < 0) {
+ throw new MockitoException("Negative value is not allowed here");
+ }
+ this.wantedCount = wantedNumberOfInvocations;
+ }
+
+ public void verify(VerificationData data) {
+ MissingInvocationChecker missingInvocation = new MissingInvocationChecker();
+ AtLeastXNumberOfInvocationsChecker numberOfInvocations = new AtLeastXNumberOfInvocationsChecker();
+
+ if (wantedCount == 1) {
+ missingInvocation.check(data.getAllInvocations(), data.getWanted());
+ }
+ numberOfInvocations.check(data.getAllInvocations(), data.getWanted(), wantedCount);
+ }
+
+ public void verifyInOrder(VerificationDataInOrder data) {
+ List<Invocation> allInvocations = data.getAllInvocations();
+ InvocationMatcher wanted = data.getWanted();
+
+ MissingInvocationInOrderChecker missingInvocation = new MissingInvocationInOrderChecker();
+ AtLeastXNumberOfInvocationsInOrderChecker numberOfCalls = new AtLeastXNumberOfInvocationsInOrderChecker(data.getOrderingContext());
+
+ if (wantedCount == 1) {
+ missingInvocation.check(allInvocations, wanted, this, data.getOrderingContext());
+ }
+
+ numberOfCalls.check(allInvocations, wanted, wantedCount);
+ }
+
+ @Override
+ public String toString() {
+ return "Wanted invocations count: at least " + wantedCount;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/AtMost.java b/src/org/mockito/internal/verification/AtMost.java
new file mode 100644
index 0000000..b705a5b
--- /dev/null
+++ b/src/org/mockito/internal/verification/AtMost.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationMarker;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+public class AtMost implements VerificationMode {
+
+ private final int maxNumberOfInvocations;
+ private final InvocationMarker invocationMarker = new InvocationMarker();
+
+ public AtMost(int maxNumberOfInvocations) {
+ if (maxNumberOfInvocations < 0) {
+ throw new MockitoException("Negative value is not allowed here");
+ }
+ this.maxNumberOfInvocations = maxNumberOfInvocations;
+ }
+
+ public void verify(VerificationData data) {
+ List<Invocation> invocations = data.getAllInvocations();
+ InvocationMatcher wanted = data.getWanted();
+
+ InvocationsFinder finder = new InvocationsFinder();
+ List<Invocation> found = finder.findInvocations(invocations, wanted);
+ int foundSize = found.size();
+ if (foundSize > maxNumberOfInvocations) {
+ new Reporter().wantedAtMostX(maxNumberOfInvocations, foundSize);
+ }
+
+ invocationMarker.markVerified(found, wanted);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/Calls.java b/src/org/mockito/internal/verification/Calls.java
new file mode 100644
index 0000000..5bdc604
--- /dev/null
+++ b/src/org/mockito/internal/verification/Calls.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.internal.verification.api.VerificationDataInOrder;
+import org.mockito.internal.verification.api.VerificationInOrderMode;
+import org.mockito.internal.verification.checkers.*;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+import java.util.List;
+
+public class Calls implements VerificationMode, VerificationInOrderMode {
+
+ final int wantedCount;
+
+ public Calls(int wantedNumberOfInvocations) {
+ if( wantedNumberOfInvocations <= 0 ) {
+ throw new MockitoException( "Negative and zero values are not allowed here" );
+ }
+ this.wantedCount = wantedNumberOfInvocations;
+ }
+
+ public void verify(VerificationData data) {
+ throw new MockitoException( "calls is only intended to work with InOrder" );
+ }
+
+ public void verifyInOrder(VerificationDataInOrder data) {
+ List<Invocation> allInvocations = data.getAllInvocations();
+ InvocationMatcher wanted = data.getWanted();
+
+ MissingInvocationInOrderChecker missingInvocation = new MissingInvocationInOrderChecker();
+ missingInvocation.check( allInvocations, wanted, this, data.getOrderingContext());
+ NonGreedyNumberOfInvocationsInOrderChecker numberOfCalls = new NonGreedyNumberOfInvocationsInOrderChecker();
+ numberOfCalls.check( allInvocations, wanted, wantedCount, data.getOrderingContext());
+ }
+
+ @Override
+ public String toString() {
+ return "Wanted invocations count (non-greedy): " + wantedCount;
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/DefaultRegisteredInvocations.java b/src/org/mockito/internal/verification/DefaultRegisteredInvocations.java
new file mode 100644
index 0000000..5ad9338
--- /dev/null
+++ b/src/org/mockito/internal/verification/DefaultRegisteredInvocations.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import org.mockito.internal.util.ObjectMethodsGuru;
+import org.mockito.internal.util.collections.ListUtil;
+import org.mockito.internal.util.collections.ListUtil.Filter;
+import org.mockito.invocation.Invocation;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+
+public class DefaultRegisteredInvocations implements RegisteredInvocations, Serializable {
+
+ private static final long serialVersionUID = -2674402327380736290L;
+ private final LinkedList<Invocation> invocations = new LinkedList<Invocation>();
+
+ public void add(Invocation invocation) {
+ synchronized (invocations) {
+ invocations.add(invocation);
+ }
+ }
+
+ public void removeLast() {
+ //TODO: add specific test for synchronization of this block (it is tested by InvocationContainerImplTest at the moment)
+ synchronized (invocations) {
+ if (! invocations.isEmpty()) {
+ invocations.removeLast();
+ }
+ }
+ }
+
+ public List<Invocation> getAll() {
+ List<Invocation> copiedList;
+ synchronized (invocations) {
+ copiedList = new LinkedList<Invocation>(invocations) ;
+ }
+
+ return ListUtil.filter(copiedList, new RemoveToString());
+ }
+
+ public boolean isEmpty() {
+ synchronized (invocations) {
+ return invocations.isEmpty();
+ }
+ }
+
+ private static class RemoveToString implements Filter<Invocation> {
+ public boolean isOut(Invocation invocation) {
+ return new ObjectMethodsGuru().isToString(invocation.getMethod());
+ }
+ }
+
+}
diff --git a/src/org/mockito/internal/verification/InOrderContextImpl.java b/src/org/mockito/internal/verification/InOrderContextImpl.java
new file mode 100644
index 0000000..5058d75
--- /dev/null
+++ b/src/org/mockito/internal/verification/InOrderContextImpl.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.internal.util.collections.IdentitySet;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+
+public class InOrderContextImpl implements InOrderContext {
+
+ final IdentitySet verified = new IdentitySet();
+
+ public boolean isVerified(Invocation invocation) {
+ return verified.contains(invocation);
+ }
+
+ public void markVerified(Invocation i) {
+ verified.add(i);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/InOrderWrapper.java b/src/org/mockito/internal/verification/InOrderWrapper.java
new file mode 100644
index 0000000..9ed1075
--- /dev/null
+++ b/src/org/mockito/internal/verification/InOrderWrapper.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.internal.InOrderImpl;
+import org.mockito.internal.invocation.finder.VerifiableInvocationsFinder;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.internal.verification.api.VerificationDataInOrderImpl;
+import org.mockito.internal.verification.api.VerificationInOrderMode;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+import java.util.List;
+
+public class InOrderWrapper implements VerificationMode {
+
+ private final VerificationInOrderMode mode;
+ private final InOrderImpl inOrder;
+
+ public InOrderWrapper(VerificationInOrderMode mode, InOrderImpl inOrder) {
+ this.mode = mode;
+ this.inOrder = inOrder;
+ }
+
+ public void verify(VerificationData data) {
+ List<Invocation> invocations = new VerifiableInvocationsFinder().find(inOrder.getMocksToBeVerifiedInOrder());
+ VerificationDataInOrderImpl dataInOrder = new VerificationDataInOrderImpl(inOrder, invocations, data.getWanted());
+ mode.verifyInOrder(dataInOrder);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/MockAwareVerificationMode.java b/src/org/mockito/internal/verification/MockAwareVerificationMode.java
new file mode 100644
index 0000000..9c4f155
--- /dev/null
+++ b/src/org/mockito/internal/verification/MockAwareVerificationMode.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.verification.VerificationMode;
+
+public class MockAwareVerificationMode implements VerificationMode {
+
+ private final Object mock;
+ private final VerificationMode mode;
+
+ public MockAwareVerificationMode(Object mock, VerificationMode mode) {
+ this.mock = mock;
+ this.mode = mode;
+ }
+
+ public void verify(VerificationData data) {
+ mode.verify(data);
+ }
+
+ public Object getMock() {
+ return mock;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/NoMoreInteractions.java b/src/org/mockito/internal/verification/NoMoreInteractions.java
new file mode 100644
index 0000000..9b7642f
--- /dev/null
+++ b/src/org/mockito/internal/verification/NoMoreInteractions.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.internal.verification.api.VerificationDataInOrder;
+import org.mockito.internal.verification.api.VerificationInOrderMode;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+public class NoMoreInteractions implements VerificationMode, VerificationInOrderMode {
+
+ @SuppressWarnings("unchecked")
+ public void verify(VerificationData data) {
+ Invocation unverified = new InvocationsFinder().findFirstUnverified(data.getAllInvocations());
+ if (unverified != null) {
+ new Reporter().noMoreInteractionsWanted(unverified, (List) data.getAllInvocations());
+ }
+ }
+
+ public void verifyInOrder(VerificationDataInOrder data) {
+ List<Invocation> invocations = data.getAllInvocations();
+ Invocation unverified = new InvocationsFinder().findFirstUnverifiedInOrder(data.getOrderingContext(), invocations);
+
+ if (unverified != null) {
+ new Reporter().noMoreInteractionsWantedInOrder(unverified);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/Only.java b/src/org/mockito/internal/verification/Only.java
new file mode 100644
index 0000000..70f1fda
--- /dev/null
+++ b/src/org/mockito/internal/verification/Only.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMarker;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+public class Only implements VerificationMode {
+
+ private final InvocationsFinder finder = new InvocationsFinder();
+ private final InvocationMarker marker = new InvocationMarker();
+ private final Reporter reporter = new Reporter();
+
+ @SuppressWarnings("unchecked")
+ public void verify(VerificationData data) {
+ InvocationMatcher wantedMatcher = data.getWanted();
+ List<Invocation> invocations = data.getAllInvocations();
+ List<Invocation> chunk = finder.findInvocations(invocations,wantedMatcher);
+ if (invocations.size() != 1 && chunk.size() > 0) {
+ Invocation unverified = finder.findFirstUnverified(invocations);
+ reporter.noMoreInteractionsWanted(unverified, (List) invocations);
+ } else if (invocations.size() != 1 || chunk.size() == 0) {
+ reporter.wantedButNotInvoked(wantedMatcher);
+ }
+ marker.markVerified(chunk.get(0), wantedMatcher);
+ }
+}
diff --git a/src/org/mockito/internal/verification/RegisteredInvocations.java b/src/org/mockito/internal/verification/RegisteredInvocations.java
new file mode 100644
index 0000000..1cb2131
--- /dev/null
+++ b/src/org/mockito/internal/verification/RegisteredInvocations.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import org.mockito.internal.util.ObjectMethodsGuru;
+import org.mockito.internal.util.collections.ListUtil;
+import org.mockito.internal.util.collections.ListUtil.Filter;
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+
+public interface RegisteredInvocations {
+
+ void add(Invocation invocation);
+
+ void removeLast();
+
+ List<Invocation> getAll();
+
+ boolean isEmpty();
+
+}
diff --git a/src/org/mockito/internal/verification/SingleRegisteredInvocation.java b/src/org/mockito/internal/verification/SingleRegisteredInvocation.java
new file mode 100644
index 0000000..07da74c
--- /dev/null
+++ b/src/org/mockito/internal/verification/SingleRegisteredInvocation.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import org.mockito.invocation.Invocation;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+public class SingleRegisteredInvocation implements RegisteredInvocations, Serializable {
+
+ private Invocation invocation;
+
+ public void add(Invocation invocation) {
+ this.invocation = invocation;
+ }
+
+ public void removeLast() {
+ invocation = null;
+ }
+
+ public List<Invocation> getAll() {
+ return Collections.emptyList();
+ }
+
+ public boolean isEmpty() {
+ return invocation == null;
+ }
+}
diff --git a/src/org/mockito/internal/verification/Times.java b/src/org/mockito/internal/verification/Times.java
new file mode 100644
index 0000000..539ddf6
--- /dev/null
+++ b/src/org/mockito/internal/verification/Times.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import java.util.List;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.internal.verification.api.VerificationDataInOrder;
+import org.mockito.internal.verification.api.VerificationInOrderMode;
+import org.mockito.internal.verification.checkers.MissingInvocationChecker;
+import org.mockito.internal.verification.checkers.MissingInvocationInOrderChecker;
+import org.mockito.internal.verification.checkers.NumberOfInvocationsChecker;
+import org.mockito.internal.verification.checkers.NumberOfInvocationsInOrderChecker;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+public class Times implements VerificationInOrderMode, VerificationMode {
+
+ final int wantedCount;
+
+ public Times(int wantedNumberOfInvocations) {
+ if (wantedNumberOfInvocations < 0) {
+ throw new MockitoException("Negative value is not allowed here");
+ }
+ this.wantedCount = wantedNumberOfInvocations;
+ }
+
+ public void verify(VerificationData data) {
+ if (wantedCount > 0) {
+ MissingInvocationChecker missingInvocation = new MissingInvocationChecker();
+ missingInvocation.check(data.getAllInvocations(), data.getWanted());
+ }
+ NumberOfInvocationsChecker numberOfInvocations = new NumberOfInvocationsChecker();
+ numberOfInvocations.check(data.getAllInvocations(), data.getWanted(), wantedCount);
+ }
+
+ public void verifyInOrder(VerificationDataInOrder data) {
+ List<Invocation> allInvocations = data.getAllInvocations();
+ InvocationMatcher wanted = data.getWanted();
+
+ if (wantedCount > 0) {
+ MissingInvocationInOrderChecker missingInvocation = new MissingInvocationInOrderChecker();
+ missingInvocation.check(allInvocations, wanted, this, data.getOrderingContext());
+ }
+ NumberOfInvocationsInOrderChecker numberOfCalls = new NumberOfInvocationsInOrderChecker();
+ numberOfCalls.check(allInvocations, wanted, wantedCount, data.getOrderingContext());
+ }
+
+ @Override
+ public String toString() {
+ return "Wanted invocations count: " + wantedCount;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/VerificationDataImpl.java b/src/org/mockito/internal/verification/VerificationDataImpl.java
new file mode 100644
index 0000000..74340c8
--- /dev/null
+++ b/src/org/mockito/internal/verification/VerificationDataImpl.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.util.ObjectMethodsGuru;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.Invocation;
+
+public class VerificationDataImpl implements VerificationData {
+
+ private final InvocationMatcher wanted;
+ private final InvocationContainer invocations;
+
+ public VerificationDataImpl(InvocationContainer invocations, InvocationMatcher wanted) {
+ this.invocations = invocations;
+ this.wanted = wanted;
+ this.assertWantedIsVerifiable();
+ }
+
+ public List<Invocation> getAllInvocations() {
+ return invocations.getInvocations();
+ }
+
+ public InvocationMatcher getWanted() {
+ return wanted;
+ }
+
+ void assertWantedIsVerifiable() {
+ if (wanted == null) {
+ return;
+ }
+ ObjectMethodsGuru o = new ObjectMethodsGuru();
+ if (o.isToString(wanted.getMethod())) {
+ new Reporter().cannotVerifyToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/VerificationModeFactory.java b/src/org/mockito/internal/verification/VerificationModeFactory.java
new file mode 100644
index 0000000..1657831
--- /dev/null
+++ b/src/org/mockito/internal/verification/VerificationModeFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification;
+
+import org.mockito.verification.VerificationMode;
+
+public class VerificationModeFactory {
+
+ public static VerificationMode atLeastOnce() {
+ return atLeast(1);
+ }
+
+ public static VerificationMode atLeast(int minNumberOfInvocations) {
+ return new AtLeast(minNumberOfInvocations);
+ }
+
+ public static VerificationMode only() {
+ return new Only(); //TODO make exception message nicer
+ }
+
+ public static Times times(int wantedNumberOfInvocations) {
+ return new Times(wantedNumberOfInvocations);
+ }
+
+ public static Calls calls(int wantedNumberOfInvocations) {
+ return new Calls( wantedNumberOfInvocations );
+ }
+
+ public static NoMoreInteractions noMoreInteractions() {
+ return new NoMoreInteractions();
+ }
+
+ public static VerificationMode atMost(int maxNumberOfInvocations) {
+ return new AtMost(maxNumberOfInvocations);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/VerificationWithTimeoutImpl.java b/src/org/mockito/internal/verification/VerificationWithTimeoutImpl.java
new file mode 100644
index 0000000..0e08005
--- /dev/null
+++ b/src/org/mockito/internal/verification/VerificationWithTimeoutImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.verification.VerificationMode;
+
+public class VerificationWithTimeoutImpl {
+
+ VerificationMode delegate;
+ int timeout;
+ int treshhold;
+
+ public VerificationWithTimeoutImpl(int treshhold, int millis, VerificationMode delegate) {
+ this.treshhold = treshhold;
+ this.timeout = millis;
+ this.delegate = delegate;
+ }
+
+ public void verify(VerificationData data) {
+ int soFar = 0;
+ MockitoAssertionError error = null;
+ while (soFar <= timeout) {
+ try {
+ delegate.verify(data);
+ return;
+ } catch (MockitoAssertionError e) {
+ error = e;
+ soFar += treshhold;
+ sleep(treshhold);
+ }
+ }
+ if (error != null) {
+ throw error;
+ }
+ }
+
+ void sleep(int sleep) {
+ try {
+ Thread.sleep(sleep);
+ } catch (InterruptedException ie) {
+ // oups. not much luck.
+ }
+ }
+
+ public VerificationMode getDelegate() {
+ return delegate;
+ }
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public int getTreshhold() {
+ return treshhold;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/api/InOrderContext.java b/src/org/mockito/internal/verification/api/InOrderContext.java
new file mode 100644
index 0000000..5186f42
--- /dev/null
+++ b/src/org/mockito/internal/verification/api/InOrderContext.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.api;
+
+import org.mockito.invocation.Invocation;
+
+public interface InOrderContext {
+
+ boolean isVerified(Invocation invocation);
+
+ void markVerified(Invocation i);
+
+}
diff --git a/src/org/mockito/internal/verification/api/VerificationData.java b/src/org/mockito/internal/verification/api/VerificationData.java
new file mode 100644
index 0000000..4ed17ae
--- /dev/null
+++ b/src/org/mockito/internal/verification/api/VerificationData.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.api;
+
+import java.util.List;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+public interface VerificationData {
+
+ List<Invocation> getAllInvocations();
+
+ InvocationMatcher getWanted();
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/api/VerificationDataInOrder.java b/src/org/mockito/internal/verification/api/VerificationDataInOrder.java
new file mode 100644
index 0000000..1abb122
--- /dev/null
+++ b/src/org/mockito/internal/verification/api/VerificationDataInOrder.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.api;
+
+import java.util.List;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+public interface VerificationDataInOrder {
+
+ List<Invocation> getAllInvocations();
+
+ InvocationMatcher getWanted();
+
+ InOrderContext getOrderingContext();
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java b/src/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java
new file mode 100644
index 0000000..7cb158b
--- /dev/null
+++ b/src/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.api;
+
+import java.util.List;
+
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.invocation.Invocation;
+
+public class VerificationDataInOrderImpl implements VerificationDataInOrder {
+
+ private final InOrderContext inOrder;
+ private final List<Invocation> allInvocations;
+ private final InvocationMatcher wanted;
+
+ public VerificationDataInOrderImpl(InOrderContext inOrder, List<Invocation> allInvocations, InvocationMatcher wanted) {
+ this.inOrder = inOrder;
+ this.allInvocations = allInvocations;
+ this.wanted = wanted;
+ }
+
+ public List<Invocation> getAllInvocations() {
+ return allInvocations;
+ }
+
+ public InOrderContext getOrderingContext() {
+ return inOrder;
+ }
+
+ public InvocationMatcher getWanted() {
+ return wanted;
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/api/VerificationInOrderMode.java b/src/org/mockito/internal/verification/api/VerificationInOrderMode.java
new file mode 100644
index 0000000..97df3f0
--- /dev/null
+++ b/src/org/mockito/internal/verification/api/VerificationInOrderMode.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.api;
+
+public interface VerificationInOrderMode {
+
+ void verifyInOrder(VerificationDataInOrder data);
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/api/package.html b/src/org/mockito/internal/verification/api/package.html
new file mode 100644
index 0000000..0001538
--- /dev/null
+++ b/src/org/mockito/internal/verification/api/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+This package should be open to public once verification API is fully finished
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java b/src/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java
new file mode 100644
index 0000000..8f983e3
--- /dev/null
+++ b/src/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.argumentmatching;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
+import org.mockito.internal.matchers.ContainsExtraTypeInformation;
+
+@SuppressWarnings("unchecked")
+public class ArgumentMatchingTool {
+
+ /**
+ * Suspiciously not matching arguments are those that don't match, the toString() representation is the same but types are different.
+ */
+ public Integer[] getSuspiciouslyNotMatchingArgsIndexes(List<Matcher> matchers, Object[] arguments) {
+ if (matchers.size() != arguments.length) {
+ return new Integer[0];
+ }
+
+ List<Integer> suspicious = new LinkedList<Integer>();
+ int i = 0;
+ for (Matcher m : matchers) {
+ if (m instanceof ContainsExtraTypeInformation
+ && !safelyMatches(m, arguments[i])
+ && toStringEquals(m, arguments[i])
+ && !((ContainsExtraTypeInformation) m).typeMatches(arguments[i])) {
+ suspicious.add(i);
+ }
+ i++;
+ }
+ return suspicious.toArray(new Integer[0]);
+ }
+
+ private boolean safelyMatches(Matcher m, Object arg) {
+ try {
+ return m.matches(arg);
+ } catch (Throwable t) {
+ return false;
+ }
+ }
+
+ private boolean toStringEquals(Matcher m, Object arg) {
+ return StringDescription.toString(m).equals(arg == null? "null" : arg.toString());
+ }
+}
diff --git a/src/org/mockito/internal/verification/argumentmatching/package.html b/src/org/mockito/internal/verification/argumentmatching/package.html
new file mode 100644
index 0000000..d71855e
--- /dev/null
+++ b/src/org/mockito/internal/verification/argumentmatching/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Deals with matching arguments
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java b/src/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java
new file mode 100644
index 0000000..0f02e9c
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.internal.verification.checkers;
+
+import org.mockito.internal.reporting.Discrepancy;
+
+public class AtLeastDiscrepancy extends Discrepancy {
+
+ public AtLeastDiscrepancy(int wantedCount, int actualCount) {
+ super(wantedCount, actualCount);
+ }
+
+ @Override
+ public String getPluralizedWantedCount() {
+ return "*at least* " + super.getPluralizedWantedCount();
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java b/src/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java
new file mode 100644
index 0000000..cc29e09
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationMarker;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+
+public class AtLeastXNumberOfInvocationsChecker {
+
+ Reporter reporter = new Reporter();
+ InvocationsFinder finder = new InvocationsFinder();
+ InvocationMarker invocationMarker = new InvocationMarker();
+
+ public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount) {
+ List<Invocation> actualInvocations = finder.findInvocations(invocations, wanted);
+
+ int actualCount = actualInvocations.size();
+ if (wantedCount > actualCount) {
+ Location lastLocation = finder.getLastLocation(actualInvocations);
+ reporter.tooLittleActualInvocations(new AtLeastDiscrepancy(wantedCount, actualCount), wanted, lastLocation);
+ }
+
+ invocationMarker.markVerified(actualInvocations, wanted);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsInOrderChecker.java b/src/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsInOrderChecker.java
new file mode 100644
index 0000000..5ed877e
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsInOrderChecker.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMarker;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+
+public class AtLeastXNumberOfInvocationsInOrderChecker {
+
+ private final Reporter reporter = new Reporter();
+ private final InvocationsFinder finder = new InvocationsFinder();
+ private final InvocationMarker invocationMarker = new InvocationMarker();
+ private final InOrderContext orderingContext;
+
+ public AtLeastXNumberOfInvocationsInOrderChecker(InOrderContext orderingContext) {
+ this.orderingContext = orderingContext;
+ }
+
+ public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount) {
+ List<Invocation> chunk = finder.findAllMatchingUnverifiedChunks(invocations, wanted, orderingContext);
+
+ int actualCount = chunk.size();
+
+ if (wantedCount > actualCount) {
+ Location lastLocation = finder.getLastLocation(chunk);
+ reporter.tooLittleActualInvocationsInOrder(new AtLeastDiscrepancy(wantedCount, actualCount), wanted, lastLocation);
+ }
+
+ invocationMarker.markVerifiedInOrder(chunk, wanted, orderingContext);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/MissingInvocationChecker.java b/src/org/mockito/internal/verification/checkers/MissingInvocationChecker.java
new file mode 100644
index 0000000..2fddf16
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/MissingInvocationChecker.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.reporting.SmartPrinter;
+import org.mockito.internal.verification.argumentmatching.ArgumentMatchingTool;
+import org.mockito.invocation.Invocation;
+
+public class MissingInvocationChecker {
+
+ private final Reporter reporter;
+ private final InvocationsFinder finder;
+
+ public MissingInvocationChecker() {
+ this(new InvocationsFinder(), new Reporter());
+ }
+
+ MissingInvocationChecker(InvocationsFinder finder, Reporter reporter) {
+ this.finder = finder;
+ this.reporter = reporter;
+ }
+
+ public void check(List<Invocation> invocations, InvocationMatcher wanted) {
+ List<Invocation> actualInvocations = finder.findInvocations(invocations, wanted);
+
+ if (actualInvocations.isEmpty()) {
+ Invocation similar = finder.findSimilarInvocation(invocations, wanted);
+ if (similar != null) {
+ ArgumentMatchingTool argumentMatchingTool = new ArgumentMatchingTool();
+ Integer[] indexesOfSuspiciousArgs = argumentMatchingTool.getSuspiciouslyNotMatchingArgsIndexes(wanted.getMatchers(), similar.getArguments());
+ SmartPrinter smartPrinter = new SmartPrinter(wanted, similar, indexesOfSuspiciousArgs);
+ reporter.argumentsAreDifferent(smartPrinter.getWanted(), smartPrinter.getActual(), similar.getLocation());
+ } else {
+ reporter.wantedButNotInvoked(wanted, invocations);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/MissingInvocationInOrderChecker.java b/src/org/mockito/internal/verification/checkers/MissingInvocationInOrderChecker.java
new file mode 100644
index 0000000..049c937
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/MissingInvocationInOrderChecker.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.reporting.SmartPrinter;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.internal.verification.argumentmatching.ArgumentMatchingTool;
+import org.mockito.invocation.Invocation;
+import org.mockito.verification.VerificationMode;
+
+public class MissingInvocationInOrderChecker {
+
+ private final Reporter reporter;
+ private final InvocationsFinder finder;
+
+ public MissingInvocationInOrderChecker() {
+ this(new InvocationsFinder(), new Reporter());
+ }
+
+ MissingInvocationInOrderChecker(InvocationsFinder finder, Reporter reporter) {
+ this.finder = finder;
+ this.reporter = reporter;
+ }
+
+ public void check(List<Invocation> invocations, InvocationMatcher wanted, VerificationMode mode, InOrderContext context) {
+ List<Invocation> chunk = finder.findAllMatchingUnverifiedChunks(invocations, wanted, context);
+
+ if (!chunk.isEmpty()) {
+ return;
+ }
+
+ Invocation previousInOrder = finder.findPreviousVerifiedInOrder(invocations, context);
+ if (previousInOrder == null) {
+ /**
+ * It is of course possible to have an issue where the arguments are different
+ * rather that not invoked in order. Issue related to
+ * http://code.google.com/p/mockito/issues/detail?id=27. If the previous order
+ * is missing, then this method checks if the arguments are different or if the order
+ * is not invoked.
+ */
+ List<Invocation> actualInvocations = finder.findInvocations(invocations, wanted);
+ if (actualInvocations == null || actualInvocations.isEmpty()) {
+ Invocation similar = finder.findSimilarInvocation(invocations, wanted);
+ if (similar != null) {
+ Integer[] indicesOfSimilarMatchingArguments =
+ new ArgumentMatchingTool().getSuspiciouslyNotMatchingArgsIndexes(wanted.getMatchers(),
+ similar.getArguments());
+ SmartPrinter smartPrinter = new SmartPrinter(wanted, similar, indicesOfSimilarMatchingArguments);
+ reporter.argumentsAreDifferent(smartPrinter.getWanted(), smartPrinter.getActual(), similar.getLocation());
+ } else {
+ reporter.wantedButNotInvoked(wanted);
+ }
+ }
+ } else {
+ reporter.wantedButNotInvokedInOrder(wanted, previousInOrder);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/NonGreedyNumberOfInvocationsInOrderChecker.java b/src/org/mockito/internal/verification/checkers/NonGreedyNumberOfInvocationsInOrderChecker.java
new file mode 100644
index 0000000..e9d73d9
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/NonGreedyNumberOfInvocationsInOrderChecker.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMarker;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.reporting.Discrepancy;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+
+import java.util.List;
+
+public class NonGreedyNumberOfInvocationsInOrderChecker {
+
+ private final InvocationsFinder finder;
+ private final Reporter reporter;
+ private final InvocationMarker marker;
+
+ public NonGreedyNumberOfInvocationsInOrderChecker() {
+ this(new InvocationsFinder(), new Reporter(), new InvocationMarker());
+ }
+
+ NonGreedyNumberOfInvocationsInOrderChecker(InvocationsFinder finder, Reporter reporter, InvocationMarker marker ) {
+ this.finder = finder;
+ this.reporter = reporter;
+ this.marker = marker;
+ }
+
+ public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount, InOrderContext context) {
+ int actualCount = 0;
+ Location lastLocation = null;
+ while( actualCount < wantedCount ){
+ Invocation next = finder.findFirstMatchingUnverifiedInvocation( invocations, wanted, context );
+ if( next == null ){
+ reporter.tooLittleActualInvocationsInOrder(new Discrepancy(wantedCount, actualCount), wanted, lastLocation );
+ }
+ marker.markVerified( next, wanted );
+ context.markVerified( next );
+ lastLocation = next.getLocation();
+ actualCount++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java b/src/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java
new file mode 100644
index 0000000..17dec9f
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationMarker;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.reporting.Discrepancy;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+
+public class NumberOfInvocationsChecker {
+
+ private final Reporter reporter;
+ private final InvocationsFinder finder;
+ private final InvocationMarker invocationMarker = new InvocationMarker();
+
+ public NumberOfInvocationsChecker() {
+ this(new Reporter(), new InvocationsFinder());
+ }
+
+ NumberOfInvocationsChecker(Reporter reporter, InvocationsFinder finder) {
+ this.reporter = reporter;
+ this.finder = finder;
+ }
+
+ public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount) {
+ List<Invocation> actualInvocations = finder.findInvocations(invocations, wanted);
+
+ int actualCount = actualInvocations.size();
+ if (wantedCount > actualCount) {
+ Location lastInvocation = finder.getLastLocation(actualInvocations);
+ reporter.tooLittleActualInvocations(new Discrepancy(wantedCount, actualCount), wanted, lastInvocation);
+ } else if (wantedCount == 0 && actualCount > 0) {
+ Location firstUndesired = actualInvocations.get(wantedCount).getLocation();
+ reporter.neverWantedButInvoked(wanted, firstUndesired);
+ } else if (wantedCount < actualCount) {
+ Location firstUndesired = actualInvocations.get(wantedCount).getLocation();
+ reporter.tooManyActualInvocations(wantedCount, actualCount, wanted, firstUndesired);
+ }
+
+ invocationMarker.markVerified(actualInvocations, wanted);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderChecker.java b/src/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderChecker.java
new file mode 100644
index 0000000..98f9f23
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderChecker.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.internal.verification.checkers;
+
+import java.util.List;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMarker;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.InvocationsFinder;
+import org.mockito.internal.reporting.Discrepancy;
+import org.mockito.internal.verification.api.InOrderContext;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.Location;
+
+public class NumberOfInvocationsInOrderChecker {
+
+ private final Reporter reporter;
+ private final InvocationsFinder finder;
+ private final InvocationMarker invocationMarker = new InvocationMarker();
+
+ public NumberOfInvocationsInOrderChecker() {
+ this(new InvocationsFinder(), new Reporter());
+ }
+
+ NumberOfInvocationsInOrderChecker(InvocationsFinder finder, Reporter reporter) {
+ this.finder = finder;
+ this.reporter = reporter;
+ }
+
+ public void check(List<Invocation> invocations, InvocationMatcher wanted, int wantedCount, InOrderContext context) {
+ List<Invocation> chunk = finder.findMatchingChunk(invocations, wanted, wantedCount, context);
+
+ int actualCount = chunk.size();
+
+ if (wantedCount > actualCount) {
+ Location lastInvocation = finder.getLastLocation(chunk);
+ reporter.tooLittleActualInvocationsInOrder(new Discrepancy(wantedCount, actualCount), wanted, lastInvocation);
+ } else if (wantedCount < actualCount) {
+ Location firstUndesired = chunk.get(wantedCount).getLocation();
+ reporter.tooManyActualInvocationsInOrder(wantedCount, actualCount, wanted, firstUndesired);
+ }
+
+ invocationMarker.markVerifiedInOrder(chunk, wanted, context);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/checkers/package.html b/src/org/mockito/internal/verification/checkers/package.html
new file mode 100644
index 0000000..a248590
--- /dev/null
+++ b/src/org/mockito/internal/verification/checkers/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+verification checkers
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/internal/verification/package.html b/src/org/mockito/internal/verification/package.html
new file mode 100644
index 0000000..171df4b
--- /dev/null
+++ b/src/org/mockito/internal/verification/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Verification logic.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/invocation/DescribedInvocation.java b/src/org/mockito/invocation/DescribedInvocation.java
new file mode 100644
index 0000000..bd8215c
--- /dev/null
+++ b/src/org/mockito/invocation/DescribedInvocation.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.invocation;
+
+import org.mockito.exceptions.PrintableInvocation;
+import org.mockito.Incubating;
+
+/**
+ * Provides information about the invocation, specifically a human readable description and the location.
+ */
+@Incubating
+public interface DescribedInvocation extends PrintableInvocation {
+
+ /**
+ * Describes the invocation in the human friendly way.
+ *
+ * @return the description of this invocation.
+ */
+ String toString();
+
+ /**
+ * The place in the code where the invocation happened.
+ *
+ * @return the location of the invocation.
+ */
+ Location getLocation();
+}
diff --git a/src/org/mockito/invocation/Invocation.java b/src/org/mockito/invocation/Invocation.java
new file mode 100644
index 0000000..34d53f6
--- /dev/null
+++ b/src/org/mockito/invocation/Invocation.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.invocation;
+
+import org.mockito.Incubating;
+
+/**
+ * A method call on a mock object. Contains all information and state needed for the Mockito framework to operate.
+ * This API might be useful for developers who extend Mockito.
+ * <p>
+ * The javadoc does not have lots of examples or documentation because its audience is different.
+ * Vast majority of users don't need to use the Invocation. It's mostly useful for other framework authors
+ * that extend Mockito.
+ *
+ * @since 1.9.5
+ */
+@Incubating
+public interface Invocation extends InvocationOnMock, DescribedInvocation {
+
+ /**
+ * @return whether the invocation has been already verified.
+ * Needed for {@link org.mockito.Mockito#verifyNoMoreInteractions(Object...)}
+ */
+ boolean isVerified();
+
+ /**
+ * @return the sequence number of the Invocation. Useful to determine the order of invocations.
+ * Used by verification in order.
+ */
+ int getSequenceNumber();
+
+ /**
+ * @return the location in code of this invocation.
+ */
+ Location getLocation();
+
+ /**
+ * Returns unprocessed arguments whereas {@link #getArguments()} returns
+ * arguments already processed (e.g. varargs expended, etc.).
+ *
+ * @return unprocessed arguments, exactly as provided to this invocation.
+ */
+ Object[] getRawArguments();
+
+ /**
+ * Marks this invocation as verified so that it will not cause verification error at
+ * {@link org.mockito.Mockito#verifyNoMoreInteractions(Object...)}
+ */
+ void markVerified();
+
+ /**
+ * @return the stubbing information for this invocation. May return null - this means
+ * the invocation was not stubbed.
+ */
+ StubInfo stubInfo();
+
+ /**
+ * Marks this invocation as stubbed.
+ *
+ * @param stubInfo the information about stubbing.
+ */
+ void markStubbed(StubInfo stubInfo);
+
+ /**
+ * Informs if the invocation participates in verify-no-more-invocations or verification in order.
+ *
+ * @return whether this invocation should be ignored for the purposes of
+ * verify-no-more-invocations or verification in order.
+ */
+ boolean isIgnoredForVerification();
+
+ /**
+ * Configures this invocation to be ignored for verify-no-more-invocations or verification in order.
+ * See also {@link #isIgnoredForVerification()}
+ */
+ void ignoreForVerification();
+}
diff --git a/src/org/mockito/invocation/InvocationOnMock.java b/src/org/mockito/invocation/InvocationOnMock.java
new file mode 100644
index 0000000..45d435a
--- /dev/null
+++ b/src/org/mockito/invocation/InvocationOnMock.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.invocation;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+/**
+ * An invocation on a mock
+ * <p>
+ * A placeholder for mock, the method that was called and the arguments that were passed.
+ */
+public interface InvocationOnMock extends Serializable {
+
+ /**
+ * returns the mock object
+ *
+ * @return mock object
+ */
+ Object getMock();
+
+ /**
+ * returns the method
+ *
+ * @return method
+ */
+ Method getMethod();
+
+ /**
+ * returns arguments passed to the method
+ *
+ * @return arguments
+ */
+ Object[] getArguments();
+
+ /**
+ * calls real method
+ * <p>
+ * <b>Warning:</b> depending on the real implementation it might throw exceptions
+ *
+ * @return whatever the real method returns / throws
+ * @throws Throwable in case real method throws
+ */
+ Object callRealMethod() throws Throwable;
+}
diff --git a/src/org/mockito/invocation/Location.java b/src/org/mockito/invocation/Location.java
new file mode 100644
index 0000000..23def6a
--- /dev/null
+++ b/src/org/mockito/invocation/Location.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.invocation;
+
+import org.mockito.Incubating;
+
+/**
+ * Describes the location of something in the source code.
+ */
+@Incubating
+public interface Location {
+
+ /**
+ * @return the location
+ */
+ String toString();
+
+}
diff --git a/src/org/mockito/invocation/MockHandler.java b/src/org/mockito/invocation/MockHandler.java
new file mode 100644
index 0000000..07f68f7
--- /dev/null
+++ b/src/org/mockito/invocation/MockHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.invocation;
+
+import org.mockito.Incubating;
+
+import java.io.Serializable;
+
+/**
+ * Mockito handler of an invocation on a mock. This is a core part of the API, the heart of Mockito.
+ * See also the {@link org.mockito.plugins.MockMaker}.
+ * <p>
+ * This api is work in progress. Do not provide your own implementations.
+ * Mockito will provide you with the implementation via other {@link org.mockito.plugins.MockMaker} methods.
+ */
+@Incubating
+public interface MockHandler extends Serializable {
+ /**
+ * Takes an invocation object and handles it.
+ * <p>
+ * The default implementation provided by Mockito handles invocations by recording
+ * method calls on mocks for further verification, captures the stubbing information when mock is stubbed,
+ * returns the stubbed values for invocations that have been stubbed, and much more.
+ *
+ * @param invocation The invocation to handle
+ * @return Result
+ * @throws Throwable Throwable
+ */
+ @Incubating
+ Object handle(Invocation invocation) throws Throwable;
+}
diff --git a/src/org/mockito/invocation/StubInfo.java b/src/org/mockito/invocation/StubInfo.java
new file mode 100644
index 0000000..0eb271f
--- /dev/null
+++ b/src/org/mockito/invocation/StubInfo.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.invocation;
+
+import org.mockito.Incubating;
+
+/**
+ * The information about stubbing, for example the location of stubbing.
+ */
+@Incubating
+public interface StubInfo {
+
+ /**
+ * @return the location where the invocation was stubbed.
+ */
+ Location stubbedAt();
+}
diff --git a/src/org/mockito/invocation/package.html b/src/org/mockito/invocation/package.html
new file mode 100644
index 0000000..e6742e2
--- /dev/null
+++ b/src/org/mockito/invocation/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Public API related to invocation
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/listeners/InvocationListener.java b/src/org/mockito/listeners/InvocationListener.java
new file mode 100644
index 0000000..13476e1
--- /dev/null
+++ b/src/org/mockito/listeners/InvocationListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.listeners;
+
+import org.mockito.MockSettings;
+
+/**
+ * This listener can be notified of method invocations on a mock.
+ *
+ * For this to happen, it must be registered using {@link MockSettings#invocationListeners(InvocationListener...)}.
+ */
+public interface InvocationListener {
+
+ /**
+ * Called after the invocation of the listener's mock if it returned normally.
+ *
+ * <p>
+ * Exceptions caused by this invocationListener will raise a {@link org.mockito.exceptions.base.MockitoException}.
+ * </p>
+ *
+ * @param methodInvocationReport Information about the method call that just happened.
+ *
+ * @see MethodInvocationReport
+ */
+ void reportInvocation(MethodInvocationReport methodInvocationReport);
+}
diff --git a/src/org/mockito/listeners/MethodInvocationReport.java b/src/org/mockito/listeners/MethodInvocationReport.java
new file mode 100644
index 0000000..002233f
--- /dev/null
+++ b/src/org/mockito/listeners/MethodInvocationReport.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.listeners;
+
+import org.mockito.exceptions.PrintableInvocation;
+import org.mockito.invocation.DescribedInvocation;
+
+/**
+ * Represent a method call on a mock.
+ *
+ * <p>
+ * Contains the information on the mock, the location of the stub
+ * the return value if it returned something (maybe null), or an
+ * exception if one was thrown when the method was invoked.
+ * </p>
+ */
+public interface MethodInvocationReport {
+ /**
+ * The return type is deprecated, please assign the return value from this method
+ * to the {@link DescribedInvocation} type. Sorry for inconvenience but we had to move
+ * {@link PrintableInvocation} to better place to keep the API consistency.
+ *
+ * @return Information on the method call, never {@code null}
+ */
+ DescribedInvocation getInvocation();
+
+ /**
+ * @return The resulting value of the method invocation, may be <code>null</code>
+ */
+ Object getReturnedValue();
+
+ /**
+ * @return The throwable raised by the method invocation, maybe <code>null</code>
+ */
+ Throwable getThrowable();
+
+ /**
+ * @return <code>true</code> if an exception was raised, <code>false</code> otherwise
+ */
+ boolean threwException();
+
+ /**
+ * @return Location of the stub invocation
+ */
+ String getLocationOfStubbing();
+}
diff --git a/src/org/mockito/listeners/package.html b/src/org/mockito/listeners/package.html
new file mode 100644
index 0000000..098d0ed
--- /dev/null
+++ b/src/org/mockito/listeners/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Public classes relative to the call listener.
+</body>
diff --git a/src/org/mockito/mock/MockCreationSettings.java b/src/org/mockito/mock/MockCreationSettings.java
new file mode 100644
index 0000000..8f561a0
--- /dev/null
+++ b/src/org/mockito/mock/MockCreationSettings.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.mock;
+
+import org.mockito.Incubating;
+import org.mockito.listeners.InvocationListener;
+import org.mockito.stubbing.Answer;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Informs about the mock settings. An immutable view of {@link org.mockito.MockSettings}.
+ */
+@Incubating
+public interface MockCreationSettings<T> {
+
+ /**
+ * Mocked type. An interface or class the mock should implement / extend.
+ */
+ Class<T> getTypeToMock();
+
+ /**
+ * the extra interfaces the mock object should implement.
+ */
+ Set<Class> getExtraInterfaces();
+
+ /**
+ * the name of this mock, as printed on verification errors; see {@link org.mockito.MockSettings#name}.
+ */
+ MockName getMockName();
+
+ /**
+ * the default answer for this mock, see {@link org.mockito.MockSettings#defaultAnswer}.
+ */
+ Answer getDefaultAnswer();
+
+ /**
+ * the spied instance - needed for spies.
+ */
+ Object getSpiedInstance();
+
+ /**
+ * if the mock is serializable, see {@link org.mockito.MockSettings#serializable}.
+ */
+ boolean isSerializable();
+
+ /**
+ * Whether the mock is only for stubbing, i.e. does not remember
+ * parameters on its invocation and therefore cannot
+ * be used for verification
+ */
+ boolean isStubOnly();
+
+ /**
+ * the invocation listeners attached to this mock, see {@link org.mockito.MockSettings#invocationListeners}.
+ */
+ List<InvocationListener> getInvocationListeners();
+}
\ No newline at end of file
diff --git a/src/org/mockito/mock/MockName.java b/src/org/mockito/mock/MockName.java
new file mode 100644
index 0000000..d3f6e7d
--- /dev/null
+++ b/src/org/mockito/mock/MockName.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.mock;
+
+/**
+ * Represents the name of the mock as shown in the verification failure reports, etc.
+ */
+public interface MockName {
+
+ /**
+ * the name
+ */
+ String toString();
+
+ /**
+ * default name means generated by Mockito. non-default means the user has named the mock at creation.
+ */
+ boolean isDefault();
+}
diff --git a/src/org/mockito/package.html b/src/org/mockito/package.html
new file mode 100644
index 0000000..e54efb3
--- /dev/null
+++ b/src/org/mockito/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+Mockito is a mock library for java - see Mockito class for for usage.
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/plugins/MockMaker.java b/src/org/mockito/plugins/MockMaker.java
new file mode 100644
index 0000000..c97dfb5
--- /dev/null
+++ b/src/org/mockito/plugins/MockMaker.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007 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.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+
+/**
+ * The facility to create mocks.
+ *
+ * <p>By default, an internal cglib/asm/objenesis based implementation is used.</p>
+ *
+ * <p>{@code MockMaker} is an extension point that makes it possible to use custom dynamic proxies
+ * and avoid using the default cglib/asm/objenesis implementation.
+ * For example, the android users can use a MockMaker that can work with Dalvik virtual machine
+ * and hence bring Mockito to android apps developers.</p>
+ *
+ * <h3>Using the extension point</h3>
+ *
+ * <p>Suppose you wrote an extension to create mocks with some <em>Awesome</em> library, in order to tell
+ * Mockito to use it you need to put in your <strong>classpath</strong>:
+ * <ol style="list-style-type: lower-alpha">
+ * <li>The implementation itself, for example <code>org.awesome.mockito.AwesomeMockMaker</code> that extends the <code>MockMaker</code>.</li>
+ * <li>A file "<code>mockito-extensions/org.mockito.plugins.MockMaker</code>". The content of this file is
+ * exactly a <strong>one</strong> line with the qualified name: <code>org.awesome.mockito.AwesomeMockMaker</code>.</li>
+ * </ol></p>
+ *
+ * <p>Note that if several <code>mockito-extensions/org.mockito.plugins.MockMaker</code> files exists in the classpath
+ * Mockito will only use the first returned by the standard {@link ClassLoader#getResource} mechanism.
+ *
+ * @see org.mockito.mock.MockCreationSettings
+ * @see org.mockito.invocation.MockHandler
+ * @since 1.9.5
+ */
+@Incubating
+public interface MockMaker {
+
+ /**
+ * If you want to provide your own implementation of {@code MockMaker} this method should:
+ * <ul>
+ * <li>Create a proxy object that implements {@code settings.typeToMock} and potentially also {@code settings.extraInterfaces}.</li>
+ * <li>You may use the information from {@code settings} to create/configure your proxy object.</li>
+ * <li>Your proxy object should carry the {@code handler} with it. For example, if you generate byte code
+ * to create the proxy you could generate an extra field to keep the {@code handler} with the generated object.
+ * Your implementation of {@code MockMaker} is required to provide this instance of {@code handler} when
+ * {@link #getHandler(Object)} is called.
+ * </li>
+ * </ul>
+ *
+ * @param settings - mock creation settings like type to mock, extra interfaces and so on.
+ * @param handler See {@link org.mockito.invocation.MockHandler}.
+ * <b>Do not</b> provide your own implementation at this time. Make sure your implementation of
+ * {@link #getHandler(Object)} will return this instance.
+ * @param <T> Type of the mock to return, actually the <code>settings.getTypeToMock</code>.
+ * @return The mock instance.
+ * @since 1.9.5
+ */
+ <T> T createMock(
+ MockCreationSettings<T> settings,
+ MockHandler handler
+ );
+
+ /**
+ * Returns the handler for the {@code mock}. <b>Do not</b> provide your own implementations at this time
+ * because the work on the {@link MockHandler} api is not completed.
+ * Use the instance provided to you by Mockito at {@link #createMock} or {@link #resetMock}.
+ *
+ * @param mock The mock instance.
+ * @return may return null - it means that there is no handler attached to provided object.
+ * This means the passed object is not really a Mockito mock.
+ * @since 1.9.5
+ */
+ MockHandler getHandler(Object mock);
+
+ /**
+ * Replaces the existing handler on {@code mock} with {@code newHandler}.
+ *
+ * <p>The invocation handler actually store invocations to achieve
+ * stubbing and verification. In order to reset the mock, we pass
+ * a new instance of the invocation handler.</p>
+ *
+ * <p>Your implementation should make sure the {@code newHandler} is correctly associated to passed {@code mock}</p>
+ *
+ * @param mock The mock instance whose invocation handler is to be replaced.
+ * @param newHandler The new invocation handler instance.
+ * @param settings The mock settings - should you need to access some of the mock creation details.
+ * @since 1.9.5
+ */
+ void resetMock(
+ Object mock,
+ MockHandler newHandler,
+ MockCreationSettings settings
+ );
+}
\ No newline at end of file
diff --git a/src/org/mockito/plugins/StackTraceCleanerProvider.java b/src/org/mockito/plugins/StackTraceCleanerProvider.java
new file mode 100644
index 0000000..ee0f998
--- /dev/null
+++ b/src/org/mockito/plugins/StackTraceCleanerProvider.java
@@ -0,0 +1,28 @@
+package org.mockito.plugins;
+
+import org.mockito.Incubating;
+import org.mockito.exceptions.stacktrace.StackTraceCleaner;
+
+/**
+ * An extension point to register custom {@link StackTraceCleaner}.
+ * You can replace Mockito's default StackTraceCleaner.
+ * You can also 'enhance' Mockito's default behavior
+ * because the default cleaner is passed as parameter to the method.
+ * <p>
+ * For more information how to register custom StackTraceCleaner
+ * please refer to the documentation of {@link MockMaker}.
+ * We will update the documentation shortly.
+ * <p>
+ * See the default implementation: {@link org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleanerProvider}
+ */
+@Incubating
+public interface StackTraceCleanerProvider {
+
+ /**
+ * Allows configuring custom StackTraceCleaner.
+ *
+ * @param defaultCleaner - Mockito's default StackTraceCleaner
+ * @return StackTraceCleaner to use
+ */
+ StackTraceCleaner getStackTraceCleaner(StackTraceCleaner defaultCleaner);
+}
\ No newline at end of file
diff --git a/src/org/mockito/runners/ConsoleSpammingMockitoJUnitRunner.java b/src/org/mockito/runners/ConsoleSpammingMockitoJUnitRunner.java
new file mode 100644
index 0000000..637f932
--- /dev/null
+++ b/src/org/mockito/runners/ConsoleSpammingMockitoJUnitRunner.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.runners;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.mockito.internal.debugging.WarningsCollector;
+import org.mockito.internal.runners.RunnerFactory;
+import org.mockito.internal.runners.RunnerImpl;
+import org.mockito.internal.util.ConsoleMockitoLogger;
+import org.mockito.internal.util.MockitoLogger;
+
+/**
+ * Uses <b>JUnit 4.5</b> runner {@link BlockJUnit4ClassRunner}.
+ * <p>
+ * Experimental implementation that suppose to improve tdd/testing experience.
+ * Don't hesitate to send feedback to mockito@googlegroups.com
+ * <b>It is very likely it will change in the next version!</b>
+ * <p>
+ * This runner does exactly what {@link MockitoJUnitRunner} does but also
+ * prints warnings that might be useful.
+ * The point is that Mockito should help the tdd developer to quickly figure out if the test fails for the right reason.
+ * Then the developer can implement the functionality.
+ * Also when the test fails it should be easy to figure out why the test fails.
+ * <p>
+ * Sometimes when the test fails, the underlying reason is that stubbed method was called with wrong arguments.
+ * Sometimes it fails because one forgets to stub a method or forgets to call a stubbed method.
+ * All above problems are not immediately obvious.
+ * <p>
+ * One way of approaching this problem is full-blown 'expect' API.
+ * However it means the 'expectations upfront' business which is not in line with core Mockito concepts.
+ * After all, the essence of testing are <b>explicit assertions</b> that are described consistently at the <b>bottom of the test</b> method.
+ * <p>
+ * Here's the experiment: a warning is printed to the standard output if the test fails.
+ * Also, you get a clickabe link to the line of code. You can immediately jump to the place in code where the potential problem is.
+ * <p>
+ * Let's say your test fails on assertion.
+ * Let's say the underlying reason is a stubbed method that was called with different arguments:
+ * <pre class="code"><code class="java">
+ * //test:
+ * Dictionary dictionary = new Dictionary(translator);
+ * when(translator.translate("Mockito")).thenReturn("cool framework");
+ * String translated = dictionary.search("Mockito");
+ * assertEquals("cool framework", translated);
+ *
+ * //code:
+ * public String search(String word) {
+ * ...
+ * return translator.translate("oups");
+ *
+ * </code></pre>
+ * On standard output you'll see something like that:
+ * <pre class="code"><code class="java">
+ * [Mockito] Warning - stubbed method called with different arguments.
+ * Stubbed this way:
+ * translator.translate("Mockito");
+ * org.dictionary.SmartDictionaryTest.shouldFindTranslation(SmartDictionaryTest.java:27)
+ *
+ * But called with different arguments:
+ * translator.translate("oups");
+ * org.dictionary.SmartDictionary.search(SmartDictionary.java:15)
+ * </code></pre>
+ * <p>
+ * Note that it is just a warning, not an assertion.
+ * The test fails on assertion because it's the assertion's duty to document what the test stands for and what behavior it proves.
+ * Warnings just makes it quicker to figure out if the test fails for the right reason.
+ * <p>
+ * Note that code links printed to the console are clickable in any decent IDE (e.g. Eclipse).
+ * <p>
+ * So far I identified 2 cases when warnings are printed:
+ * <li>unsued stub</li>
+ * <li>stubbed method but called with different arguments</li>
+ * <p>
+ * <br/>
+ * <p>
+ * Do you think it is useful or not? Drop us an email at mockito@googlegroups.com
+ */
+public class ConsoleSpammingMockitoJUnitRunner extends Runner implements Filterable {
+
+ private final MockitoLogger logger;
+ private RunnerImpl runner;
+
+ public ConsoleSpammingMockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {
+ this(new ConsoleMockitoLogger(), new RunnerFactory().create(klass));
+ }
+
+ ConsoleSpammingMockitoJUnitRunner(MockitoLogger logger, RunnerImpl runnerImpl) {
+ this.runner = runnerImpl;
+ this.logger = logger;
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ RunListener listener = new RunListener() {
+ WarningsCollector warningsCollector;
+
+ @Override
+ public void testStarted(Description description) throws Exception {
+ warningsCollector = new WarningsCollector();
+ }
+
+ @Override public void testFailure(Failure failure) throws Exception {
+ logger.log(warningsCollector.getWarnings());
+ }
+ };
+
+ notifier.addListener(listener);
+
+ runner.run(notifier);
+ }
+
+ @Override
+ public Description getDescription() {
+ return runner.getDescription();
+ }
+
+ public void filter(Filter filter) throws NoTestsRemainException {
+ //filter is required because without it UnrootedTests show up in Eclipse
+ runner.filter(filter);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/runners/MockitoJUnit44Runner.java b/src/org/mockito/runners/MockitoJUnit44Runner.java
new file mode 100644
index 0000000..4080d1e
--- /dev/null
+++ b/src/org/mockito/runners/MockitoJUnit44Runner.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.runners;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * <b>Deprecated: Simply use {@link MockitoJUnitRunner}</b>
+ * <p>
+ * Compatible only with <b>JUnit 4.4</b>, this runner adds following behavior:
+ * <ul>
+ * <li>
+ * Initializes mocks annotated with {@link Mock},
+ * so that explicit usage of {@link MockitoAnnotations#initMocks(Object)} is not necessary.
+ * Mocks are initialized before each test method.
+ * <li>
+ * validates framework usage after each test method. See javadoc for {@link Mockito#validateMockitoUsage()}.
+ * </ul>
+ *
+ * Runner is completely optional - there are other ways you can get @Mock working, for example by writing a base class.
+ * Explicitly validating framework usage is also optional because it is triggered automatically by Mockito every time you use the framework.
+ * See javadoc for {@link Mockito#validateMockitoUsage()}.
+ * <p>
+ * Read more about @Mock annotation in javadoc for {@link MockitoAnnotations}
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * @RunWith(MockitoJUnitRunner.class)
+ * public class ExampleTest {
+ *
+ * @Mock
+ * private List list;
+ *
+ * @Test
+ * public void shouldDoSomething() {
+ * list.add(100);
+ * }
+ * }
+ * <p>
+ *
+ * </code></pre>
+ */
+@Deprecated
+public class MockitoJUnit44Runner extends MockitoJUnitRunner {
+
+ public MockitoJUnit44Runner(Class<?> klass) throws InvocationTargetException {
+ super(klass);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/runners/MockitoJUnitRunner.java b/src/org/mockito/runners/MockitoJUnitRunner.java
new file mode 100644
index 0000000..e065d96
--- /dev/null
+++ b/src/org/mockito/runners/MockitoJUnitRunner.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.runners;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.runners.RunnerFactory;
+import org.mockito.internal.runners.RunnerImpl;
+
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * Compatible with <b>JUnit 4.4 and higher</b>, this runner adds following behavior:
+ * <ul>
+ * <li>
+ * Initializes mocks annotated with {@link Mock},
+ * so that explicit usage of {@link MockitoAnnotations#initMocks(Object)} is not necessary.
+ * Mocks are initialized before each test method.
+ * <li>
+ * validates framework usage after each test method. See javadoc for {@link Mockito#validateMockitoUsage()}.
+ * </ul>
+ *
+ * Runner is completely optional - there are other ways you can get @Mock working, for example by writing a base class.
+ * Explicitly validating framework usage is also optional because it is triggered automatically by Mockito every time you use the framework.
+ * See javadoc for {@link Mockito#validateMockitoUsage()}.
+ * <p>
+ * Read more about @Mock annotation in javadoc for {@link MockitoAnnotations}
+ * <pre class="code"><code class="java">
+ * <b>@RunWith(MockitoJUnitRunner.class)</b>
+ * public class ExampleTest {
+ *
+ * @Mock
+ * private List list;
+ *
+ * @Test
+ * public void shouldDoSomething() {
+ * list.add(100);
+ * }
+ * }
+ * </code></pre>
+ */
+public class MockitoJUnitRunner extends Runner implements Filterable {
+
+ private final RunnerImpl runner;
+
+ public MockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {
+ runner = new RunnerFactory().create(klass);
+ }
+
+ @Override
+ public void run(final RunNotifier notifier) {
+ runner.run(notifier);
+ }
+
+ @Override
+ public Description getDescription() {
+ return runner.getDescription();
+ }
+
+ public void filter(Filter filter) throws NoTestsRemainException {
+ //filter is required because without it UnrootedTests show up in Eclipse
+ runner.filter(filter);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/runners/VerboseMockitoJUnitRunner.java b/src/org/mockito/runners/VerboseMockitoJUnitRunner.java
new file mode 100644
index 0000000..d98d831
--- /dev/null
+++ b/src/org/mockito/runners/VerboseMockitoJUnitRunner.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.runners;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.mockito.internal.debugging.WarningsCollector;
+import org.mockito.internal.runners.RunnerFactory;
+import org.mockito.internal.runners.RunnerImpl;
+import org.mockito.internal.util.junit.JUnitFailureHacker;
+
+/**
+ * Experimental implementation that suppose to improve tdd/testing experience.
+ * Don't hesitate to send feedback to mockito@googlegroups.com
+ * <b>It is very likely it will change in the next version!</b>
+ * <p>
+ * This runner does exactly what {@link MockitoJUnitRunner} does but also
+ * adds extra Mocktio hints to the exception message.
+ * The point is that Mockito should help the tdd developer to quickly figure out if the test fails for the right reason and track the reason.
+ * <p>
+ * The implemntation is pretty hacky - it uses brute force of reflection to modify the exception message and add extra mockito hints.
+ * You've been warned.
+ * <p>
+ * Do you think it is useful or not? Drop us an email at mockito@googlegroups.com
+ * <p>
+ * Experimental implementation - will change in future!
+ */
+public class VerboseMockitoJUnitRunner extends Runner implements Filterable {
+
+ private RunnerImpl runner;
+
+ public VerboseMockitoJUnitRunner(Class<?> klass) throws InvocationTargetException {
+ this(new RunnerFactory().create(klass));
+ }
+
+ VerboseMockitoJUnitRunner(RunnerImpl runnerImpl) {
+ this.runner = runnerImpl;
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+
+ //a listener that changes the failure's exception in a very hacky way...
+ RunListener listener = new RunListener() {
+
+ WarningsCollector warningsCollector;
+
+ @Override
+ public void testStarted(Description description) throws Exception {
+ warningsCollector = new WarningsCollector();
+ }
+
+ @Override
+ public void testFailure(final Failure failure) throws Exception {
+ String warnings = warningsCollector.getWarnings();
+ new JUnitFailureHacker().appendWarnings(failure, warnings);
+ }
+ };
+
+ notifier.addFirstListener(listener);
+
+ runner.run(notifier);
+ }
+
+ @Override
+ public Description getDescription() {
+ return runner.getDescription();
+ }
+
+ public void filter(Filter filter) throws NoTestsRemainException {
+ //filter is required because without it UnrootedTests show up in Eclipse
+ runner.filter(filter);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/runners/package.html b/src/org/mockito/runners/package.html
new file mode 100644
index 0000000..2ce69b8
--- /dev/null
+++ b/src/org/mockito/runners/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+JUnit runners.
+</body>
diff --git a/src/org/mockito/stubbing/Answer.java b/src/org/mockito/stubbing/Answer.java
new file mode 100644
index 0000000..784a268
--- /dev/null
+++ b/src/org/mockito/stubbing/Answer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.invocation.InvocationOnMock;
+
+/**
+ * Generic interface to be used for configuring mock's answer.
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).thenAnswer(new Answer() {
+ * Object answer(InvocationOnMock invocation) {
+ * Object[] args = invocation.getArguments();
+ * Object mock = invocation.getMock();
+ * return "called with arguments: " + args;
+ * }
+ * });
+ *
+ * //Following prints "called with arguments: foo"
+ * System.out.println(mock.someMethod("foo"));
+ * </code></pre>
+ *
+ * @param <T> the type to return.
+ */
+public interface Answer<T> {
+ /**
+ * @param invocation the invocation on the mock.
+ *
+ * @return the value to be returned
+ *
+ * @throws Throwable the throwable to be thrown
+ */
+ T answer(InvocationOnMock invocation) throws Throwable;
+}
\ No newline at end of file
diff --git a/src/org/mockito/stubbing/DeprecatedOngoingStubbing.java b/src/org/mockito/stubbing/DeprecatedOngoingStubbing.java
new file mode 100644
index 0000000..d41137f
--- /dev/null
+++ b/src/org/mockito/stubbing/DeprecatedOngoingStubbing.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Mockito;
+import org.mockito.internal.progress.IOngoingStubbing;
+
+/**
+ * Stubs a method call with return value or an exception. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * stub(mock.someMethod()).toReturn(10);
+ *
+ * //you can use flexible argument matchers, e.g:
+ * stub(mock.someMethod(<b>anyString()</b>)).toReturn(10);
+ *
+ * //setting exception to be thrown:
+ * stub(mock.someMethod("some arg")).toThrow(new RuntimeException());
+ *
+ * //you can stub with different behavior for consecutive method calls.
+ * //Last stubbing (e.g: toReturn("foo")) determines the behavior for further consecutive calls.
+ * stub(mock.someMethod("some arg"))
+ * .toThrow(new RuntimeException())
+ * .toReturn("foo");
+ *
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito#stub}
+ */
+public interface DeprecatedOngoingStubbing<T> extends IOngoingStubbing {
+
+ /**
+ * Set a return value for the stubbed method. E.g:
+ * <pre class="code"><code class="java">
+ * stub(mock.someMethod()).toReturn(10);
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito#stub}
+ *
+ * @param value return value
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ */
+ DeprecatedOngoingStubbing<T> toReturn(T value);
+
+ /**
+ * Set a Throwable to be thrown when the stubbed method is called. E.g:
+ * <pre class="code"><code class="java">
+ * stub(mock.someMethod()).toThrow(new RuntimeException());
+ * </code></pre>
+ *
+ * If throwable is a checked exception then it has to
+ * match one of the checked exceptions of method signature.
+ *
+ * See examples in javadoc for {@link Mockito#stub}
+ *
+ * @param throwable to be thrown on method invocation
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ */
+ DeprecatedOngoingStubbing<T> toThrow(Throwable throwable);
+
+ /**
+ * Set a generic Answer for the stubbed method. E.g:
+ * <pre class="code"><code class="java">
+ * stub(mock.someMethod(10)).toAnswer(new Answer<Integer>() {
+ * public Integer answer(InvocationOnMock invocation) throws Throwable {
+ * return (Integer) invocation.getArguments()[0];
+ * }
+ * }
+ * </code></pre>
+ *
+ * @param answer the custom answer to execute.
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ */
+ DeprecatedOngoingStubbing<T> toAnswer(Answer<?> answer);
+}
\ No newline at end of file
diff --git a/src/org/mockito/stubbing/OngoingStubbing.java b/src/org/mockito/stubbing/OngoingStubbing.java
new file mode 100644
index 0000000..c60f724
--- /dev/null
+++ b/src/org/mockito/stubbing/OngoingStubbing.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Mockito;
+import org.mockito.internal.progress.IOngoingStubbing;
+
+/**
+ * Simply put: "<b>When</b> the x method is called <b>then</b> return y". E.g:
+ *
+ * <pre class="code"><code class="java">
+ * <b>when</b>(mock.someMethod()).<b>thenReturn</b>(10);
+ *
+ * //you can use flexible argument matchers, e.g:
+ * when(mock.someMethod(<b>anyString()</b>)).thenReturn(10);
+ *
+ * //setting exception to be thrown:
+ * when(mock.someMethod("some arg")).thenThrow(new RuntimeException());
+ *
+ * //you can set different behavior for consecutive method calls.
+ * //Last stubbing (e.g: thenReturn("foo")) determines the behavior of further consecutive calls.
+ * when(mock.someMethod("some arg"))
+ * .thenThrow(new RuntimeException())
+ * .thenReturn("foo");
+ *
+ * //There is a shorter way of consecutive stubbing:
+ * when(mock.someMethod()).thenReturn(1,2,3);
+ * when(mock.otherMethod()).thenThrow(exc1, exc2);
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito#when}
+ */
+public interface OngoingStubbing<T> extends IOngoingStubbing {
+
+ /**
+ * Sets a return value to be returned when the method is called. E.g:
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod()).thenReturn(10);
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito#when}
+ *
+ * @param value return value
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ */
+ OngoingStubbing<T> thenReturn(T value);
+
+ /**
+ * Sets consecutive return values to be returned when the method is called. E.g:
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod()).thenReturn(1, 2, 3);
+ * </code></pre>
+ *
+ * Last return value in the sequence (in example: 3) determines the behavior of further consecutive calls.
+ * <p>
+ * See examples in javadoc for {@link Mockito#when}
+ *
+ * @param value first return value
+ * @param values next return values
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ */
+ OngoingStubbing<T> thenReturn(T value, T... values);
+
+ /**
+ * Sets Throwable objects to be thrown when the method is called. E.g:
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod()).thenThrow(new RuntimeException());
+ * </code></pre>
+ *
+ * If throwables contain a checked exception then it has to
+ * match one of the checked exceptions of method signature.
+ * <p>
+ * You can specify throwables to be thrown for consecutive calls.
+ * In that case the last throwable determines the behavior of further consecutive calls.
+ * <p>
+ * if throwable is null then exception will be thrown.
+ * <p>
+ * See examples in javadoc for {@link Mockito#when}
+ *
+ * @param throwables to be thrown on method invocation
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ */
+ OngoingStubbing<T> thenThrow(Throwable... throwables);
+
+ /**
+ * Sets Throwable classes to be thrown when the method is called. E.g:
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod()).thenThrow(RuntimeException.class);
+ * </code></pre>
+ *
+ * <p>
+ * Each throwable class will be instantiated for each method invocation.
+ * <p>
+ * If throwableClasses contain a checked exception then it has to
+ * match one of the checked exceptions of method signature.
+ * <p>
+ * You can specify throwableClasses to be thrown for consecutive calls.
+ * In that case the last throwable determines the behavior of further consecutive calls.
+ * <p>
+ * if throwable is null then exception will be thrown.
+ * <p>
+ * See examples in javadoc for {@link Mockito#when}
+ *
+ * @param throwableClasses to be thrown on method invocation
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ * @since 1.9.0
+ */
+ OngoingStubbing<T> thenThrow(Class<? extends Throwable>... throwableClasses);
+
+ /**
+ * Sets the real implementation to be called when the method is called on a mock object.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>:
+ * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
+ * How does partial mock fit into this paradigm? Well, it just doesn't...
+ * Partial mock usually means that the complexity has been moved to a different method on the same object.
+ * In most cases, this is not the way you want to design your application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy:
+ * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
+ * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
+ * <pre class="code"><code class="java">
+ * // someMethod() must be safe (e.g. doesn't throw, doesn't have dependencies to the object state, etc.)
+ * // if it isn't safe then you will have trouble stubbing it using this api. Use Mockito.doCallRealMethod() instead.
+ * when(mock.someMethod()).thenCallRealMethod();
+ *
+ * // calls real method:
+ * mock.someMethod();
+ *
+ * </code></pre>
+ * See also javadoc {@link Mockito#spy(Object)} to find out more about partial mocks.
+ * <b>Mockito.spy() is a recommended way of creating partial mocks.</b>
+ * The reason is it guarantees real methods are called against correctly constructed object because you're responsible for constructing the object passed to spy() method.
+ * <p>
+ * See examples in javadoc for {@link Mockito#when}
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ */
+ OngoingStubbing<T> thenCallRealMethod();
+
+ /**
+ * Sets a generic Answer for the method. E.g:
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(10)).thenAnswer(new Answer<Integer>() {
+ * public Integer answer(InvocationOnMock invocation) throws Throwable {
+ * return (Integer) invocation.getArguments()[0];
+ * }
+ * }
+ * </code></pre>
+ *
+ * @param answer the custom answer to execute.
+ *
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ */
+ OngoingStubbing<T> thenAnswer(Answer<?> answer);
+
+ /**
+ * Sets a generic Answer for the method.
+ *
+ * This method is an alias of {@link #thenAnswer(Answer)}. This alias allows
+ * more readable tests on occasion, for example:
+ * <pre class="code"><code class="java">
+ * //using 'then' alias:
+ * when(mock.foo()).then(returnCoolValue());
+ *
+ * //versus good old 'thenAnswer:
+ * when(mock.foo()).thenAnswer(byReturningCoolValue());
+ * </code></pre>
+ *
+ * @param answer the custom answer to execute.
+ * @return iOngoingStubbing object that allows stubbing consecutive calls
+ *
+ * @see #thenAnswer(Answer)
+ * @since 1.9.0
+ */
+ OngoingStubbing<T> then(Answer<?> answer);
+
+ /**
+ * Returns the mock that was used for this stub.
+ * <p>
+ * It allows to create a stub in one line of code.
+ * This can be helpful to keep test code clean.
+ * For example, some boring stub can be created & stubbed at field initialization in a test:
+ * <pre class="code"><code class="java">
+ * public class CarTest {
+ * Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();
+ *
+ * @Test public void should... {}
+ * </code></pre>
+ *
+ * @param <M> The mock type given by the variable type.
+ * @return Mock used in this ongoing stubbing.
+ * @since 1.9.0
+ */
+ <M> M getMock();
+
+}
diff --git a/src/org/mockito/stubbing/Stubber.java b/src/org/mockito/stubbing/Stubber.java
new file mode 100644
index 0000000..9775628
--- /dev/null
+++ b/src/org/mockito/stubbing/Stubber.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Mockito;
+
+/**
+ * Allows to choose a method when stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * doThrow(new RuntimeException()).when(mockedList).clear();
+ *
+ * //following throws RuntimeException:
+ * mockedList.clear();
+ * </code></pre>
+ *
+ * Also useful when stubbing consecutive calls:
+ *
+ * <pre class="code"><code class="java">
+ * doThrow(new RuntimeException("one")).
+ * doThrow(new RuntimeException("two"))
+ * .when(mock).someVoidMethod();
+ * </code></pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+@SuppressWarnings("unchecked")
+public interface Stubber {
+
+ /**
+ * Allows to choose a method when stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style
+ * <p>
+ * Example:
+ * <pre class="code"><code class="java">
+ * doThrow(new RuntimeException())
+ * .when(mockedList).clear();
+ *
+ * //following throws RuntimeException:
+ * mockedList.clear();
+ * </code></pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ *
+ * @param mock The mock
+ * @return select method for stubbing
+ */
+ <T> T when(T mock);
+
+ /**
+ * Use it for stubbing consecutive calls in {@link Mockito#doThrow(Throwable)} style:
+ * <pre class="code"><code class="java">
+ * doThrow(new RuntimeException("one")).
+ * doThrow(new RuntimeException("two"))
+ * .when(mock).someVoidMethod();
+ * </code></pre>
+ * See javadoc for {@link Mockito#doThrow(Throwable)}
+ *
+ * @param toBeThrown to be thrown when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ Stubber doThrow(Throwable toBeThrown);
+
+ /**
+ * Use it for stubbing consecutive calls in {@link Mockito#doThrow(Class)} style:
+ * <pre class="code"><code class="java">
+ * doThrow(RuntimeException.class).
+ * doThrow(IllegalArgumentException.class)
+ * .when(mock).someVoidMethod();
+ * </code></pre>
+ * See javadoc for {@link Mockito#doThrow(Class)}
+ *
+ * @param toBeThrown exception class to be thrown when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ Stubber doThrow(Class<? extends Throwable> toBeThrown);
+
+ /**
+ * Use it for stubbing consecutive calls in {@link Mockito#doAnswer(Answer)} style:
+ * <pre class="code"><code class="java">
+ * doAnswer(answerOne).
+ * doAnswer(answerTwo)
+ * .when(mock).someVoidMethod();
+ * </code></pre>
+ * See javadoc for {@link Mockito#doAnswer(Answer)}
+ *
+ * @param answer to answer when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ Stubber doAnswer(Answer answer);
+
+ /**
+ * Use it for stubbing consecutive calls in {@link Mockito#doNothing()} style:
+ * <pre class="code"><code class="java">
+ * doNothing().
+ * doThrow(new RuntimeException("two"))
+ * .when(mock).someVoidMethod();
+ * </code></pre>
+ * See javadoc for {@link Mockito#doNothing()}
+ *
+ * @return stubber - to select a method for stubbing
+ */
+ Stubber doNothing();
+
+ /**
+ * Use it for stubbing consecutive calls in {@link Mockito#doReturn(Object)} style.
+ * <p>
+ * See javadoc for {@link Mockito#doReturn(Object)}
+ *
+ * @param toBeReturned to be returned when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ Stubber doReturn(Object toBeReturned);
+
+ /**
+ * Use it for stubbing consecutive calls in {@link Mockito#doCallRealMethod()} style.
+ * <p>
+ * See javadoc for {@link Mockito#doCallRealMethod()}
+ *
+ * @return stubber - to select a method for stubbing
+ */
+ Stubber doCallRealMethod();
+}
diff --git a/src/org/mockito/stubbing/VoidMethodStubbable.java b/src/org/mockito/stubbing/VoidMethodStubbable.java
new file mode 100644
index 0000000..f6f7323
--- /dev/null
+++ b/src/org/mockito/stubbing/VoidMethodStubbable.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing;
+
+import org.mockito.Mockito;
+
+/**
+ * Stubs void method with an exception. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * stubVoid(mock).toThrow(new RuntimeException()).on().someMethod();
+ *
+ * //you can stub with different behavior for consecutive method calls.
+ * //Last stubbing (e.g: toReturn()) determines the behavior for further consecutive calls.
+ * stubVoid(mock)
+ * .toThrow(new RuntimeException())
+ * .toReturn()
+ * .on().someMethod();
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito#stubVoid}
+ */
+public interface VoidMethodStubbable<T> {
+
+ /**
+ * Stubs void method with an exception. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * stubVoid(mock).toThrow(new RuntimeException()).on().someMethod();
+ * </code></pre>
+ *
+ * If throwable is a checked exception then it has to
+ * match one of the checked exceptions of method signature.
+ *
+ * See examples in javadoc for {@link Mockito#stubVoid}
+ *
+ * @param throwable to be thrown on method invocation
+ *
+ * @return VoidMethodStubbable - typically to choose void method and finish stubbing
+ */
+ VoidMethodStubbable<T> toThrow(Throwable throwable);
+
+ /**
+ * Stubs void method to 'just return' (e.g. to <b>not</b> to throw any exception)
+ * <p>
+ * <b>Only use this method if you're stubbing consecutive calls.</b>
+ * <p>
+ * For example:
+ * <pre class="code"><code class="java">
+ * stubVoid(mock)
+ * .toReturn()
+ * .toThrow(new RuntimeException())
+ * .on().foo(10);
+ * </code></pre>
+ * <ul>
+ * <li>first time foo(10) is called the mock will 'just return' (e.g. don't throw any exception)</li>
+ * <li>second time foo(10) is called the mock will throw RuntimeException</li>
+ * <li>every consecutive time foo(10) is called the mock will throw RuntimeException</li>
+ * </ul>
+ * <p>
+ * See examples in javadoc for {@link Mockito#stubVoid}
+ *
+ * @return VoidMethodStubbable - typically to choose void method and finish stubbing
+ */
+ VoidMethodStubbable<T> toReturn();
+
+ /**
+ * Stubs a void method with generic {@link Answer}
+ * <p>
+ * For Example:
+ * <pre class="code"><code class="java">
+ * stubVoid(mock)
+ * .toAnswer(new Answer() {
+ * public Object answer(InvocationOnMOck invocation) {
+ * Visitor v = (Visitor) invocation.getArguments()[0];
+ * v.visitMock(invocation.getMock());
+ *
+ * return null;
+ * }
+ * })
+ * .on().accept(any());
+ * </code></pre>
+ *
+ * @param answer the custom answer to execute.
+ *
+ * @return VoidMethodStubbable - typically to choose void method and finish stubbing
+ */
+ VoidMethodStubbable<T> toAnswer(Answer<?> answer);
+
+ /**
+ * Choose void method for stubbing. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * stubVoid(mock).toThrow(new RuntimeException()).on().someMethod("some arg");
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito#stubVoid}
+ *
+ * @return mock object itself
+ */
+ T on();
+}
\ No newline at end of file
diff --git a/src/org/mockito/stubbing/answers/ReturnsElementsOf.java b/src/org/mockito/stubbing/answers/ReturnsElementsOf.java
new file mode 100644
index 0000000..efaf2f9
--- /dev/null
+++ b/src/org/mockito/stubbing/answers/ReturnsElementsOf.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.stubbing.answers;
+
+import java.util.Collection;
+
+/**
+ * Returns elements of the collection. Keeps returning the last element forever.
+ * Might be useful on occasion when you have a collection of elements to return.
+ * <p>
+ * <pre class="code"><code class="java">
+ * //this:
+ * when(mock.foo()).thenReturn(1, 2, 3);
+ * //is equivalent to:
+ * when(mock.foo()).thenReturn(new ReturnsElementsOf(Arrays.asList(1, 2, 3)));
+ * </code></pre>
+ *
+ * @deprecated Use {@link org.mockito.AdditionalAnswers#returnsElementsOf}
+ */
+@Deprecated
+public class ReturnsElementsOf extends org.mockito.internal.stubbing.answers.ReturnsElementsOf {
+
+ @Deprecated
+ public ReturnsElementsOf(Collection<?> elements) {
+ super(elements);
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/stubbing/package.html b/src/org/mockito/stubbing/package.html
new file mode 100644
index 0000000..55e28cc
--- /dev/null
+++ b/src/org/mockito/stubbing/package.html
@@ -0,0 +1,8 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>
+External stubbing related classes
+</body>
\ No newline at end of file
diff --git a/src/org/mockito/verification/Timeout.java b/src/org/mockito/verification/Timeout.java
new file mode 100644
index 0000000..e120622
--- /dev/null
+++ b/src/org/mockito/verification/Timeout.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockito.verification;
+
+import org.mockito.exceptions.Reporter;
+import org.mockito.exceptions.misusing.FriendlyReminderException;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.internal.verification.VerificationWithTimeoutImpl;
+import org.mockito.internal.verification.api.VerificationData;
+
+/**
+ * See the javadoc for {@link VerificationWithTimeout}
+ * <p>
+ * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class.
+ * See javadoc for {@link VerificationWithTimeout}
+ */
+public class Timeout implements VerificationWithTimeout {
+
+ VerificationWithTimeoutImpl impl;
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ * <p>
+ * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class.
+ * See javadoc for {@link VerificationWithTimeout}
+ */
+ public Timeout(int millis, VerificationMode delegate) {
+ this(10, millis, delegate);
+ }
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ */
+ Timeout(int treshhold, int millis, VerificationMode delegate) {
+ this.impl = new VerificationWithTimeoutImpl(treshhold, millis, delegate);
+ }
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ */
+ public void verify(VerificationData data) {
+ impl.verify(data);
+ }
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ */
+ public VerificationMode atLeast(int minNumberOfInvocations) {
+ return new Timeout(impl.getTreshhold(), impl.getTimeout(), VerificationModeFactory.atLeast(minNumberOfInvocations));
+ }
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ */
+ public VerificationMode atLeastOnce() {
+ return new Timeout(impl.getTreshhold(), impl.getTimeout(), VerificationModeFactory.atLeastOnce());
+ }
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ */
+ public VerificationMode atMost(int maxNumberOfInvocations) {
+ new Reporter().atMostShouldNotBeUsedWithTimeout();
+ return null;
+ }
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ */
+ public VerificationMode never() {
+ return new Timeout(impl.getTreshhold(), impl.getTimeout(), VerificationModeFactory.times(0));
+ }
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ */
+ public VerificationMode only() {
+ return new Timeout(impl.getTreshhold(), impl.getTimeout(), VerificationModeFactory.only());
+ }
+
+ /**
+ * See the javadoc for {@link VerificationWithTimeout}
+ */
+ public VerificationMode times(int wantedNumberOfInvocations) {
+ return new Timeout(impl.getTreshhold(), impl.getTimeout(), VerificationModeFactory.times(wantedNumberOfInvocations));
+ }
+}
\ No newline at end of file
diff --git a/src/org/mockito/verification/VerificationMode.java b/src/org/mockito/verification/VerificationMode.java
new file mode 100644
index 0000000..a436d97
--- /dev/null
+++ b/src/org/mockito/verification/VerificationMode.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.verification;
+
+import org.mockito.Mockito;
+import org.mockito.internal.verification.api.VerificationData;
+
+/**
+ * Allows verifying that certain behavior happened at least once / exact number
+ * of times / never. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * verify(mock, times(5)).someMethod("was called five times");
+ *
+ * verify(mock, never()).someMethod("was never called");
+ *
+ * verify(mock, atLeastOnce()).someMethod("was called at least once");
+ *
+ * verify(mock, atLeast(2)).someMethod("was called at least twice");
+ *
+ * verify(mock, atMost(3)).someMethod("was called at most 3 times");
+ *
+ * </code></pre>
+ *
+ * <b>times(1) is the default</b> and can be omitted
+ * <p>
+ * See examples in javadoc for {@link Mockito#verify(Object, VerificationMode)}
+ */
+public interface VerificationMode {
+
+ void verify(VerificationData data);
+
+}
\ No newline at end of file
diff --git a/src/org/mockito/verification/VerificationWithTimeout.java b/src/org/mockito/verification/VerificationWithTimeout.java
new file mode 100644
index 0000000..0b4c923
--- /dev/null
+++ b/src/org/mockito/verification/VerificationWithTimeout.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.mockito.verification;
+
+import org.mockito.Mockito;
+
+/**
+ * VerificationWithTimeout is a {@link VerificationMode} that allows combining existing verification modes with 'timeout'. E.g:
+ *
+ * <pre class="code"><code class="java">
+ * verify(mock, timeout(100).times(5)).foo();
+ *
+ * verify(mock, timeout(100).never()).bar();
+ *
+ * verify(mock, timeout(200).atLeastOnce()).baz();
+ * </code></pre>
+ *
+ * <p>
+ * See examples in javadoc for {@link Mockito#verify(Object, VerificationMode)}
+ */
+public interface VerificationWithTimeout extends VerificationMode {
+
+ /**
+ * Allows verifying exact number of invocations within given timeout
+ * <pre class="code"><code class="java">
+ * verify(mock, timeout(100).times(2)).someMethod("some arg");
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param wantedNumberOfInvocations wanted number of invocations
+ *
+ * @return verification mode
+ */
+ public VerificationMode times(int wantedNumberOfInvocations);
+
+ /**
+ * Alias to times(0), see {@link #times(int)}
+ * <p>
+ * Verifies that interaction did not happen within given timeout. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, timeout(100).never()).someMethod();
+ * </code></pre>
+ *
+ * <p>
+ * If you want to verify there were NO interactions with the mock
+ * check out {@link Mockito#verifyNoMoreInteractions(Object...)}
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return verification mode
+ */
+ public VerificationMode never();
+
+ /**
+ * Allows at-least-once verification withing given timeout. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, timeout(100).atLeastOnce()).someMethod("some arg");
+ * </code></pre>
+ * Alias to atLeast(1)
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return verification mode
+ */
+ public VerificationMode atLeastOnce();
+
+ /**
+ * Allows at-least-x verification withing given timeout. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, timeout(100).atLeast(3)).someMethod("some arg");
+ * </code></pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param minNumberOfInvocations minimum number of invocations
+ *
+ * @return verification mode
+ */
+ public VerificationMode atLeast(int minNumberOfInvocations);
+
+ /**
+ * @deprecated
+ *
+ * <b>Deprecated</b>
+ * validation with timeout combined with atMost simply does not make sense...
+ * The test would have passed immediately in the concurrent environment
+ * <p>
+ * To avoid compilation erros upon upgrade the method is deprecated and it throws a "friendly reminder" exception.
+ * <p>
+ * In future release we will remove timeout(x).atMost(y) from the API.
+ * <p>
+ * Do you want to find out more? See <a href="http://code.google.com/p/mockito/issues/detail?id=235">issue 235</a>
+ *
+ * @return verification mode
+ */
+ @Deprecated
+ public VerificationMode atMost(int maxNumberOfInvocations);
+
+ /**
+ * Allows checking if given method was the only one invoked. E.g:
+ * <pre class="code"><code class="java">
+ * verify(mock, only()).someMethod();
+ * //above is a shorthand for following 2 lines of code:
+ * verify(mock).someMethod();
+ * verifyNoMoreInvocations(mock);
+ * </code></pre>
+ *
+ * <p>
+ * See also {@link Mockito#verifyNoMoreInteractions(Object...)}
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return verification mode
+ */
+ public VerificationMode only();
+}
\ No newline at end of file