/*
* Copyright (c) 2006 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import java.math.*;
import java.util.*;
import java.util.concurrent.*;
import static java.util.Arrays.*;
import org.junit.*;
import org.junit.rules.*;
import static org.junit.Assert.*;
public final class ExpectationsUsingResultFieldTest
{
@Rule public final ExpectedException thrown = ExpectedException.none();
static class Collaborator
{
static String doInternal() { return "123"; }
void provideSomeService() {}
int getValue() { return -1; }
Integer getInteger() { return -1; }
byte getByteValue() { return -1; }
Byte getByteWrapper() { return -1; }
short getShortValue() { return -1; }
Short getShortWrapper() { return -1; }
long getLongValue() { return -1; }
Long getLongWrapper() { return -1L; }
float getFloatValue() { return -1.0F; }
Float getFloatWrapper() { return -1.0F; }
double getDoubleValue() { return -1.0; }
Double getDoubleWrapper() { return -1.0; }
char getCharValue() { return '1'; }
Character getCharacter() { return '1'; }
boolean getBooleanValue() { return true; }
Boolean getBooleanWrapper() { return true; }
String getString() { return ""; }
Object getObject() { return null; }
Collection<?> getItems() { return null; }
List<?> getListItems() { return null; }
Set<?> getSetItems() { return null; }
SortedSet<?> getSortedSetItems() { return null; }
Map<?, ?> getMapItems() { return null; }
SortedMap<?, ?> getSortedMapItems() { return null; }
Iterator<?> getIterator() { return null; }
ListIterator<?> getListIterator() { return null; }
Iterable<?> getIterable() { return null; }
int[] getIntArray() { return null; }
int[][] getInt2Array() { return null; }
byte[] getByteArray() { return null; }
short[] getShortArray() { return null; }
Short[] getShortWrapperArray() { return null; }
long[] getLongArray() { return null; }
long[][] getLong2Array() { return null; }
float[] getFloatArray() { return null; }
double[] getDoubleArray() { return null; }
char[] getCharArray() { return null; }
boolean[] getBooleanArray() { return null; }
String[] getStringArray() { return null; }
String[][] getString2Array() { return null; }
<T extends Number> T[] getArrayOfGenericElements(@SuppressWarnings("unused") int i) { return null; }
Collection<Number> getNumbers() { return null; }
List<Number> getNumberList() { return null; }
Set<String> getStringSet() { return null; }
SortedSet<Number> getSortedNumberSet() { return null; }
Iterator<String> getStringIterator() { return null; }
ListIterator<Float> getFloatIterator() { return null; }
Iterable<Number> getNumberIterable() { return null; }
Queue<Number> getNumberQueue() { return null; }
}
@Test
public void returnsExpectedValuesFromStrictExpectations(@Mocked final Collaborator mock)
{
new StrictExpectations() {{
mock.getValue(); result = 3;
Collaborator.doInternal(); result = "test";
}};
assertEquals(3, mock.getValue());
assertEquals("test", Collaborator.doInternal());
}
@Test
public void returnsExpectedValues(@Mocked final Collaborator mock)
{
new Expectations() {{
mock.getValue(); result = 3;
Collaborator.doInternal(); result = "test";
}};
assertEquals(3, mock.getValue());
assertEquals("test", Collaborator.doInternal());
}
@Test
public void recordThrownException(@Mocked final Collaborator mock)
{
thrown.expect(ArithmeticException.class);
new Expectations() {{
mock.provideSomeService(); result = new ArithmeticException("test");
}};
mock.provideSomeService();
}
@Test
public void recordThrownError(@Mocked final Collaborator mock)
{
thrown.expect(LinkageError.class);
new Expectations() {{
mock.provideSomeService(); result = new LinkageError("test");
}};
mock.provideSomeService();
}
@Test
public void recordThrowingOfMockException(
@Mocked final Collaborator mock, @Mocked final IllegalFormatWidthException e)
{
new Expectations() {{
mock.provideSomeService(); result = e;
e.getMessage(); result = "foo";
}};
try {
mock.provideSomeService();
}
catch (Throwable t) {
assertEquals("foo", t.getMessage());
}
}
@Test
public void returnsMultipleExpectedValues(@Mocked final Collaborator mock)
{
new Expectations() {{
mock.getValue(); result = 1; result = 2; result = 3;
}};
assertEquals(1, mock.getValue());
assertEquals(2, mock.getValue());
assertEquals(3, mock.getValue());
}
@Test
public void returnsMultipleExpectedValuesWithMoreInvocationsAllowed(@Mocked final Collaborator mock)
{
new Expectations() {{
mock.getValue(); result = 1; result = 2; times = 3;
}};
assertEquals(1, mock.getValue());
assertEquals(2, mock.getValue());
assertEquals(2, mock.getValue());
}
@Test
public void returnsNullAsDefaultValueForMethodsReturningStringOrObject(@Mocked Collaborator mock)
{
assertNull(mock.getString());
assertNull(Collaborator.doInternal());
assertNull(mock.getObject());
}
@Test
public void returnsDefaultValuesForPrimitiveAndWrapperReturnTypes(@Mocked Collaborator mock)
{
assertEquals(0, mock.getValue());
assertEquals(0, mock.getInteger().intValue());
assertEquals((byte) 0, mock.getByteValue());
assertEquals(0, mock.getByteWrapper().intValue());
assertEquals((short) 0, mock.getShortValue());
assertEquals(0, mock.getShortWrapper().intValue());
assertEquals(0L, mock.getLongValue());
assertEquals(0L, mock.getLongWrapper().longValue());
assertEquals(0.0F, mock.getFloatValue(), 0.0);
assertEquals(0.0F, mock.getFloatWrapper(), 0);
assertEquals(0.0, mock.getDoubleValue(), 0.0);
assertEquals(0.0, mock.getDoubleWrapper(), 0);
assertEquals('\0', mock.getCharValue());
assertEquals('\0', mock.getCharacter().charValue());
assertFalse(mock.getBooleanValue());
assertFalse(mock.getBooleanWrapper());
}
@Test
public void returnsDefaultValuesForCollectionValuedReturnTypes(@Mocked Collaborator mock)
{
assertSame(Collections.emptyList(), mock.getItems());
assertSame(Collections.emptyList(), mock.getListItems());
assertSame(Collections.emptySet(), mock.getSetItems());
assertEquals(Collections.emptySet(), mock.getSortedSetItems());
assertSame(Collections.emptyMap(), mock.getMapItems());
assertEquals(Collections.emptyMap(), mock.getSortedMapItems());
}
@Test
public void returnsDefaultValuesForIteratorAndIterableReturnTypes(@Mocked Collaborator mock)
{
assertFalse(mock.getIterator().hasNext());
assertFalse(mock.getListIterator().hasNext());
assertFalse(mock.getIterable().iterator().hasNext());
}
@Test
public void returnsDefaultValuesForArrayValuedReturnTypes(@Mocked Collaborator mock)
{
assertArrayEquals(new int[0], mock.getIntArray());
assertArrayEquals(new int[0][0], mock.getInt2Array());
assertArrayEquals(new byte[0], mock.getByteArray());
assertArrayEquals(new short[0], mock.getShortArray());
assertArrayEquals(new Short[0], mock.getShortWrapperArray());
assertArrayEquals(new long[0], mock.getLongArray());
assertArrayEquals(new long[0][0], mock.getLong2Array());
assertArrayEquals(new float[0], mock.getFloatArray(), 0.0F);
assertArrayEquals(new double[0], mock.getDoubleArray(), 0.0);
assertArrayEquals(new char[0], mock.getCharArray());
assertEquals(0, mock.getBooleanArray().length);
assertArrayEquals(new String[0], mock.getStringArray());
assertArrayEquals(new String[0][0], mock.getString2Array());
}
@Test
public void returnsMultipleValuesInSequenceUsingCollection()
{
final Collaborator collaborator = new Collaborator();
final Set<Boolean> booleanSet = new LinkedHashSet<Boolean>(asList(true, false));
final Collection<Integer> intCol = asList(1, 2, 3);
final List<Character> charList = asList('a', 'b', 'c');
new Expectations(collaborator) {{
collaborator.getBooleanWrapper(); result = booleanSet;
collaborator.getInteger(); result = intCol;
collaborator.getCharValue(); result = charList;
}};
assertTrue(collaborator.getBooleanWrapper());
assertFalse(collaborator.getBooleanWrapper());
assertEquals(1, collaborator.getInteger().intValue());
assertEquals(2, collaborator.getInteger().intValue());
assertEquals(3, collaborator.getInteger().intValue());
assertEquals('a', collaborator.getCharValue());
assertEquals('b', collaborator.getCharValue());
assertEquals('c', collaborator.getCharValue());
}
@Test
public void returnsMultipleValuesInSequenceUsingIterator()
{
final Collaborator collaborator = new Collaborator();
final Collection<String> strCol = asList("ab", "cde", "Xyz");
new Expectations(collaborator) {{
collaborator.getString(); result = strCol.iterator();
}};
assertEquals("ab", collaborator.getString());
assertEquals("cde", collaborator.getString());
assertEquals("Xyz", collaborator.getString());
}
@Test
public void returnsMultipleValuesInSequenceUsingArray(@Injectable final Collaborator collaborator)
{
final boolean[] arrayOfBooleanPrimitives = {true, false};
final Boolean[] arrayOfBooleanWrappers = {Boolean.TRUE, Boolean.FALSE};
final int[] intArray = {1, 2, 3};
final Character[] charArray = {'a', 'b', 'c'};
new Expectations() {{
collaborator.getBooleanValue(); result = arrayOfBooleanPrimitives;
collaborator.getBooleanWrapper(); result = arrayOfBooleanWrappers;
collaborator.getValue(); result = intArray;
collaborator.getCharValue(); result = charArray;
}};
assertTrue(collaborator.getBooleanValue());
assertFalse(collaborator.getBooleanValue());
assertTrue(collaborator.getBooleanWrapper());
assertFalse(collaborator.getBooleanWrapper());
assertEquals(1, collaborator.getValue());
assertEquals(2, collaborator.getValue());
assertEquals(3, collaborator.getValue());
assertEquals('a', collaborator.getCharValue());
assertEquals('b', collaborator.getCharValue());
assertEquals('c', collaborator.getCharValue());
}
@Test
public void returnsMultipleValuesInSequenceUsingIterable(@Injectable final Collaborator collaborator)
{
final Iterable<Integer> intValues = new Iterable<Integer>() {
@Override public Iterator<Integer> iterator() { return asList(3, 2, 1).iterator(); }
};
new Expectations() {{
collaborator.getValue(); result = intValues;
}};
assertEquals(3, collaborator.getValue());
assertEquals(2, collaborator.getValue());
assertEquals(1, collaborator.getValue());
}
@Test
public void returnsMultipleValuesFromMethodWithReturnTypeOfObject(@Mocked final Collaborator collaborator)
{
new Expectations() {{
collaborator.getObject();
result = new int[] {1, 2};
result = new Object[] {"test", 'X'};
result = asList(5L, 67L);
result = null;
}};
assertArrayEquals(new int[] {1, 2}, (int[]) collaborator.getObject());
assertArrayEquals(new Object[] {"test", 'X'}, (Object[]) collaborator.getObject());
//noinspection AssertEqualsBetweenInconvertibleTypes
assertEquals(asList(5L, 67L), collaborator.getObject());
assertNull(collaborator.getObject());
assertNull(collaborator.getObject());
}
@Test
public void returnsEmptyArrayForMethodWithReturnTypeOfObject(@Mocked final Collaborator mock)
{
final String[] emptyArray = {};
new Expectations() {{
mock.getObject();
result = emptyArray;
}};
assertSame(emptyArray, mock.getObject());
}
@Test
public void returnsMultipleValuesFromGenericMethod(@Mocked final Callable<Integer> callable) throws Exception
{
new Expectations() {{
callable.call();
result = new int[] {3, 2, 1};
}};
Integer firstCall = callable.call();
assertEquals(3, firstCall.intValue());
assertEquals(2, callable.call().intValue());
assertEquals(1, callable.call().intValue());
}
@Test
public void returnsSpecifiedCollectionsForMethodsThatReturnCollections()
{
final Collaborator collaborator = new Collaborator();
final Collection<String> strCol = asList("ab", "cde");
final List<Byte> byteList = asList((byte) 5, (byte) 68);
final Set<Character> charSet = new HashSet<Character>(asList('g', 't', 'x'));
final SortedSet<String> sortedSet = new TreeSet<String>(asList("hpq", "Abc"));
new Expectations(collaborator) {{
collaborator.getItems(); result = strCol;
collaborator.getListItems(); result = byteList;
collaborator.getSetItems(); result = charSet;
collaborator.getSortedSetItems(); result = sortedSet;
}};
assertSame(strCol, collaborator.getItems());
assertSame(byteList, collaborator.getListItems());
assertSame(charSet, collaborator.getSetItems());
assertSame(sortedSet, collaborator.getSortedSetItems());
}
@Test
public void returnsSpecifiedIteratorForMethodThatReturnsIterator()
{
final Collaborator collaborator = new Collaborator();
final Iterator<String> itr = asList("ab", "cde").iterator();
new Expectations(collaborator) {{
collaborator.getIterator(); result = itr;
}};
assertSame(itr, collaborator.getIterator());
}
@Test
public void returnsValueOfIncompatibleTypeForMethodReturningArray(@Mocked final Collaborator mock)
{
new Expectations() {{
mock.getBooleanArray(); result = new HashSet();
mock.getStringArray(); result = Collections.emptyList();
mock.getIntArray(); result = new short[] {1, 2};
}};
try { mock.getBooleanArray(); fail(); } catch (ClassCastException ignore) {}
try { mock.getStringArray(); fail(); } catch (ClassCastException ignore) {}
try { mock.getIntArray(); fail(); } catch (ClassCastException ignore) {}
}
@Test
public void returnsValueOfIncompatibleTypeForMethodReturningCollection(@Mocked final Collaborator mock)
{
new Expectations() {{
mock.getListItems(); result = Collections.emptySet();
mock.getSetItems(); result = new ArrayList();
}};
try { mock.getListItems(); fail(); } catch (ClassCastException ignore) {}
try { mock.getSetItems(); fail(); } catch (ClassCastException ignore) {}
}
@Test
public void attemptToReturnValueOfTypeSetFromMethodReturningIterator(@Mocked final Collaborator mock)
{
thrown.expect(ClassCastException.class);
new Expectations() {{
mock.getIterator(); result = Collections.emptySet();
}};
mock.getIterator();
}
@Test
public void attemptToReturnValueOfTypeListFromMethodReturningIterator(@Mocked final Collaborator mock)
{
thrown.expect(ClassCastException.class);
new Expectations() {{
mock.getIterator(); result = asList("a", true, 123);
}};
mock.getIterator();
}
@Test
public void returnIterableOrIteratorFromRecordedArray(@Injectable final Collaborator mock)
{
final String[] items = {"Abc", "test"};
final int[] listItems = {1, 2, 3};
final boolean[] iterable = {false, true};
final Boolean[] iterator = {true, false, true};
final Object[] listIterator = {"test", 123, true};
new Expectations() {{
mock.getItems(); result = items;
mock.getListItems(); result = listItems;
mock.getSetItems(); result = new char[] {'A', 'c', 'b', 'A'};
mock.getSortedSetItems(); result = new Object[] {"test", "123", "abc"};
mock.getIterable(); result = iterable;
mock.getIterator(); result = iterator;
mock.getListIterator(); result = listIterator;
}};
assertEquals(Arrays.toString(items), mock.getItems().toString());
assertEquals(Arrays.toString(listItems), mock.getListItems().toString());
assertEquals("[A, c, b]", mock.getSetItems().toString());
assertEquals("[123, abc, test]", mock.getSortedSetItems().toString());
assertEquals(Arrays.toString(iterable), mock.getIterable().toString());
assertEquals(asList(iterator), fromIterator(mock.getIterator()));
assertEquals(asList(listIterator), fromIterator(mock.getListIterator()));
}
private List<?> fromIterator(Iterator<?> itr)
{
List<Object> values = new ArrayList<Object>();
while (itr.hasNext()) {
values.add(itr.next());
}
return values;
}
@Test
public void returnMapFromRecordedTwoDimensionalArray(
@Injectable final Collaborator mock1, @Injectable final Collaborator mock2)
{
final int[][] sortedItems1 = {{13, 1}, {2, 2}, {31, 3}, {5, 4}};
final Object[][] items2 = {{1, "first"}, {2}, {3, true}};
new Expectations() {{
mock1.getMapItems(); result = new String[][] {{"Abc", "first"}, {"test", "Second"}, {"Xyz", null}};
mock1.getSortedMapItems(); result = sortedItems1;
mock2.getMapItems(); result = items2;
}};
assertEquals("{Abc=first, test=Second, Xyz=null}", mock1.getMapItems().toString());
assertEquals("{2=2, 5=4, 13=1, 31=3}", mock1.getSortedMapItems().toString());
assertEquals("{1=first, 2=null, 3=true}", mock2.getMapItems().toString());
}
@Test
public void recordNullReturnValueForConstructor(@Mocked Collaborator mock)
{
new Expectations() {{ new Collaborator(); result = null; }};
new Collaborator().provideSomeService();
}
@Test
public void recordNullReturnValueForVoidMethod(@Mocked final Collaborator mock)
{
new Expectations() {{ mock.provideSomeService(); result = null; }};
new Collaborator().provideSomeService();
}
@Test
public void recordNullReturnValueForVoidMethodAndThenAThrownError(@Mocked final Collaborator mock)
{
thrown.expect(UnknownError.class);
new Expectations() {{
mock.provideSomeService();
result = null;
result = new UnknownError();
}};
try {
mock.provideSomeService();
}
catch (Throwable ignore) {
fail();
}
mock.provideSomeService();
}
@Test
public void throwExceptionFromSecondInvocationOfConstructor(@Mocked Collaborator mock)
{
thrown.expect(NoSuchElementException.class);
new Expectations() {{
new Collaborator();
result = null; result = new NoSuchElementException();
}};
try {
new Collaborator();
}
catch (NoSuchElementException ignore) {
fail();
}
new Collaborator();
}
@Test
public void recordReturnValueForVoidMethod(@Mocked final Collaborator mock)
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("incompatible with return type void");
thrown.expectMessage("Integer");
new Expectations() {{
mock.provideSomeService();
result = 123;
}};
}
@Test
public void recordConsecutiveReturnValuesForVoidMethod(@Mocked final Collaborator mock)
{
new Expectations() {{
mock.provideSomeService();
result = new int[] {123, 45}; // will have the effect of allowing two invocations
}};
mock.provideSomeService();
mock.provideSomeService();
}
@Test
public void recordReturnValueForConstructor(@Mocked Collaborator mock)
{
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("String");
thrown.expectMessage("incompatible with return type void");
new Expectations() {{
new Collaborator();
result = "test"; // invalid, throws IllegalArgumentException
}};
}
@Test
public void recordReturnValuesMixedWithThrowablesForNonVoidMethod(@Mocked final Collaborator mock)
{
new Expectations() {{
mock.getString();
result = asList("Abc", new IllegalStateException(), "DEF", null, new UnknownError());
}};
Collaborator c = new Collaborator();
assertEquals("Abc", c.getString());
try { c.getString(); fail(); } catch (IllegalStateException ignored) {}
assertEquals("DEF", c.getString());
assertNull(c.getString());
try { c.getString(); fail(); } catch (UnknownError ignored) {}
try { c.getString(); fail(); } catch (UnknownError ignored) {}
}
@Test
public void recordExceptionFollowedByNullReturnValueForVoidMethod(@Mocked final Collaborator mock)
{
new StrictExpectations() {{
// One way of doing it:
mock.provideSomeService();
result = new IllegalArgumentException();
result = null;
// Another way:
mock.provideSomeService();
result = asList(new IllegalArgumentException(), null);
// Yet another way:
mock.provideSomeService();
result = asList(new IllegalArgumentException(), null).iterator();
}};
for (int i = 0; i < 3; i++) {
try { mock.provideSomeService(); fail(); } catch (IllegalArgumentException ignored) {}
mock.provideSomeService();
}
}
@Test
public void recordArraysOfGenericElementTypes(@Mocked final Collaborator mock)
{
final Integer[] integerValues = {1, 2};
final Number[] numberValues = {5L, 12.5F};
final String[] stringValues = {"a", "b"};
new Expectations() {{
mock.getArrayOfGenericElements(1); result = integerValues;
mock.getArrayOfGenericElements(2); result = numberValues;
mock.getArrayOfGenericElements(3); result = stringValues;
}};
assertSame(numberValues, mock.getArrayOfGenericElements(2));
assertSame(integerValues, mock.getArrayOfGenericElements(1));
try { mock.getArrayOfGenericElements(3); fail(); } catch (ClassCastException ignore) {}
}
@Test
public void createArrayFromSingleRecordedValueOfTheElementType(@Mocked final Collaborator mock)
{
new Expectations() {{
mock.getIntArray(); result = 123;
mock.getStringArray(); result = "test";
}};
assertArrayEquals(new int[] {123}, mock.getIntArray());
assertArrayEquals(new String[] {"test"}, mock.getStringArray());
}
@Test
public void createAppropriateContainerFromSingleRecordedValueOfTheElementType(@Mocked final Collaborator mock)
{
final Double d = 1.2;
final Float f = 3.45F;
final BigDecimal price = new BigDecimal("123.45");
new Expectations() {{
mock.getNumbers(); result = 123;
mock.getNumberList(); result = 45L;
mock.getStringSet(); result = "test";
mock.getSortedNumberSet(); result = d;
mock.getNumberIterable(); result = price;
mock.getNumberQueue(); result = d;
mock.getStringIterator(); result = "Abc";
mock.getFloatIterator(); result = f;
}};
assertContainerWithSingleElement(mock.getNumbers(), 123);
assertContainerWithSingleElement(mock.getNumberList(), 45L);
assertContainerWithSingleElement(mock.getStringSet(), "test");
assertContainerWithSingleElement(mock.getSortedNumberSet(), d);
assertContainerWithSingleElement(mock.getNumberIterable(), price);
assertContainerWithSingleElement(mock.getNumberQueue(), d);
assertContainerWithSingleElement(mock.getStringIterator(), "Abc");
assertContainerWithSingleElement(mock.getFloatIterator(), f);
}
void assertContainerWithSingleElement(Iterable<?> container, Object expectedElement)
{
assertContainerWithSingleElement(container.iterator(), expectedElement);
}
void assertContainerWithSingleElement(Iterator<?> container, Object expectedElement)
{
assertTrue(container.hasNext());
assertSame(expectedElement, container.next());
assertFalse(container.hasNext());
}
}