/*
* 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 static java.util.Arrays.*;
import static java.util.Collections.singletonList;
import org.junit.*;
import org.junit.rules.*;
import static org.junit.Assert.*;
import mockit.internal.*;
@SuppressWarnings("ConstantConditions")
public final class WithCaptureTest
{
@Rule public final ExpectedException thrown = ExpectedException.none();
public static class Person
{
private String name;
private int age;
@SuppressWarnings("UnusedDeclaration") public Person() {}
public Person(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public int getAge() { return age; }
}
public interface DAO<T> { void create(T t); }
@SuppressWarnings("UnusedParameters")
public static final class PersonDAO implements DAO<Person>
{
@Override public void create(Person p) {}
public Person create(String name, int age) { return new Person(name, age); }
public void doSomething(Integer i) {}
public void doSomething(boolean b) {}
public void doSomething(Number n) {}
public void doSomethingElse(Number n) {}
public void doSomething(Number[] nums) {}
public void doSomething(List<Integer> nums) {}
public void doSomething(
String s1, boolean b, String s2, double d, float f, long l, Object o, char c, byte bt, short sh) {}
void doSomething(String[] names, int[] ages) {}
void doSomething(Float f1, float f2, boolean... flags) {}
void doSomething(String name, Short age) {}
}
@Mocked PersonDAO dao;
@Test
public void captureArgumentFromLastMatchingInvocationToLocalVariable()
{
dao.create("Mary Jane", 10);
dao.create("John", 25);
new FullVerifications() {{
int age;
dao.create(null, age = withCapture());
assertTrue(age >= 18);
}};
}
@Test
public void captureArgumentOfWrapperTypeToLocalVariableOfPrimitiveType()
{
dao.doSomething(45);
new Verifications() {{
int i;
dao.doSomething(i = withCapture());
assertEquals(45, i);
}};
}
@Test
public void captureArgumentOfReferenceTypeToLocalVariableOfPrimitiveType()
{
dao.doSomething(123.0F);
new Verifications() {{
float f;
dao.doSomething(f = withCapture());
assertEquals(123.0F, f, 0);
}};
}
@Test
public void captureArgumentToVariableOfSpecificSubtypeForSeparateInvocations()
{
dao.doSomething(new BigInteger("9999"));
dao.doSomething((byte) -123);
dao.doSomething(123.0F);
dao.doSomething(1234L);
dao.doSomething(1234.5);
new Verifications() {{
BigInteger bi;
dao.doSomething(bi = withCapture());
assertEquals(9999, bi.intValue());
Float f;
dao.doSomething(f = withCapture());
assertEquals(123.0F, f, 0);
long l;
dao.doSomething(l = withCapture());
assertEquals(1234L, l);
Double d;
dao.doSomething(d = withCapture());
assertEquals(1234.5, d, 0);
byte b;
dao.doSomething(b = withCapture());
assertEquals(-123, b);
}};
}
@Test
public void captureArrayArgumentsToVariablesWithSpecificElementSubtypes()
{
final Integer[] ints = {1, 2, 3};
dao.doSomething(ints);
final Double[] doubles = {1.0, 2.5, -3.2};
dao.doSomething(doubles);
final BigInteger[] bigInts = {new BigInteger("12"), new BigInteger("45")};
dao.doSomething(bigInts);
new FullVerificationsInOrder() {{
Integer[] capturedInts;
dao.doSomething(capturedInts = withCapture());
assertSame(ints, capturedInts);
Double[] capturedDoubles;
dao.doSomething(capturedDoubles = withCapture());
assertSame(doubles, capturedDoubles);
BigInteger[] capturedBigInts;
dao.doSomething(capturedBigInts = withCapture());
assertSame(bigInts, capturedBigInts);
}};
}
@Test
public void captureArgumentOfPrimitiveTypeToLocalVariableOfPrimitiveType()
{
dao.doSomething(true);
new Verifications() {{
boolean b;
dao.doSomething(b = withCapture());
assertTrue(b);
}};
}
@Test
public void captureArgumentOfPrimitiveTypeToLocalVariableOfReferenceType()
{
dao.doSomething(true);
new Verifications() {{
Boolean b;
dao.doSomething(b = withCapture());
assertTrue(b);
}};
}
@Test
public void captureArgumentsToLocalVariables()
{
final Person p = new Person("John", 10);
dao.create(p);
dao.create("Mary Jane", 30);
dao.doSomething("test", true, "Test", 4.5, -2.3F, 123, p, 'g', (byte) 127, (short) -32767);
new Verifications() {{
Person created;
dao.create(created = withCapture());
assertEquals("John", created.getName());
assertEquals(10, created.getAge());
String name;
int age;
dao.create(name = withCapture(), age = withCapture());
assertEquals("Mary Jane", name);
assertEquals(30, age);
String s1;
boolean b;
double d;
float f;
long l;
Object o;
char c;
byte bt;
short sh;
dao.doSomething(
s1 = withCapture(), b = withCapture(), "Test", d = withCapture(),
f = withCapture(), l = withCapture(), o = withCapture(),
c = withCapture(), bt = withCapture(), sh = withCapture());
assertEquals("test", s1);
assertTrue(b);
assertEquals(4.5, d, 0);
assertEquals(-2.3, f, 0.001);
assertEquals(123, l);
assertSame(p, o);
assertEquals('g', c);
assertEquals(127, bt);
assertEquals(-32767, sh);
}};
}
@Test
public void attemptToCaptureArgumentsIntoFields()
{
dao.doSomething(56);
new Verifications() {
Integer i;
{
dao.doSomething(i = withCapture());
assertNull(i);
}
};
}
@Test
public void captureFirstArgumentInTwoParameterMethod()
{
final String name1 = "Ted";
final Short age = 15;
dao.doSomething(name1, age);
final String name2 = "Jane";
dao.doSomething(name2, age);
new VerificationsInOrder() {{
String nameCapture;
dao.doSomething(nameCapture = withCapture(), age);
assertEquals(name1, nameCapture);
String strCapture;
dao.doSomething(strCapture = withCapture(), age);
assertEquals(name2, strCapture);
}};
}
@Test
public void captureArgumentsForInvocationAlreadyMatchedByRecordedExpectation()
{
new Expectations() {{ dao.doSomething(anyString, anyShort); }};
dao.doSomething("testing", (short) 15);
new Verifications() {{
String s;
short i;
dao.doSomething(s = withCapture(), i = withCapture());
assertEquals("testing", s);
assertEquals(15, i);
}};
}
@Test
public void captureArgumentsFromConsecutiveMatchingInvocations()
{
dao.doSomething((byte) 56);
dao.doSomething(123.4F);
dao.doSomething((short) -78);
dao.doSomething(91);
dao.doSomething(92);
final String[] names1 = {"Ted"};
final int[] ages1 = {15, 46};
dao.doSomething(names1, ages1);
final String[] names2 = {"Jane"};
final int[] ages2 = {101};
dao.doSomething(names2, ages2);
new VerificationsInOrder() {{
byte bt;
dao.doSomething(bt = withCapture());
assertEquals(56, bt);
Number n;
dao.doSomething(n = withCapture());
assertEquals(123.4, n.floatValue(), 0.001);
short sh;
dao.doSomething(sh = withCapture());
assertEquals(-78, sh);
int i1;
dao.doSomething(i1 = withCapture());
assertEquals(91, i1);
Integer i2;
dao.doSomething(i2 = withCapture());
assertEquals(92, i2.intValue());
String[] namesCapture;
int[] agesCapture;
dao.doSomething(namesCapture = withCapture(), agesCapture = withCapture());
assertSame(names1, namesCapture);
assertSame(ages1, agesCapture);
dao.doSomething(namesCapture = withCapture(), agesCapture = withCapture());
assertSame(names2, namesCapture);
assertSame(ages2, agesCapture);
}};
}
@Test
public void captureArrayArguments()
{
final String[] names = {"Ted", "Lisa"};
final int[] ages = {67, 19};
dao.doSomething(names, ages);
new Verifications() {{
String[] capturedNames;
int[] capturedAges;
dao.doSomething(capturedNames = withCapture(), capturedAges = withCapture());
assertArrayEquals(names, capturedNames);
assertArrayEquals(ages, capturedAges);
}};
}
@Test
public void captureVarargsParameter()
{
dao.doSomething(1.2F, 1.0F, true, false, true);
dao.doSomething(0.0F, 2.0F, false, true);
dao.doSomething(-2.0F, 3.0F);
new VerificationsInOrder() {{
boolean[] flags;
dao.doSomething(anyFloat, 1.0F, flags = withCapture());
assertEquals(3, flags.length);
assertTrue(flags[0]);
assertFalse(flags[1]);
assertTrue(flags[2]);
dao.doSomething(null, 2.0F, flags = withCapture());
assertEquals(2, flags.length);
assertFalse(flags[0]);
assertTrue(flags[1]);
dao.doSomething(withAny(0.0F), 3.0F, flags = withCapture());
assertEquals(0, flags.length);
}};
}
@Test
public void captureArgumentsWhileMixingAnyFieldsAndLiteralValuesAndCallsToOtherMethods()
{
final double d = 4.5;
final long l = 123;
dao.doSomething("Test", true, "data", d, 12.25F, l, "testing", '9', (byte) 11, (short) 5);
new Verifications() {{
float f;
String s;
byte b;
//noinspection ConstantMathCall
dao.doSomething(
null, anyBoolean, getData(), Math.abs(-d), f = withCapture(), Long.valueOf("" + l),
s = withCapture(), Character.forDigit(9, 10), b = withCapture(), anyShort);
assertEquals(12.25F, f, 0);
assertEquals("testing", s);
assertEquals(11, b);
}};
}
private String getData() { return "data"; }
@Test
public void captureArgumentsIntoListInExpectationBlock()
{
final List<Person> personsCreated = new ArrayList<Person>();
final List<String> personNames = new LinkedList<String>();
final List<Integer> personAges = new LinkedList<Integer>();
new Expectations() {{
dao.create(withCapture(personsCreated));
dao.create(withCapture(personNames), withCapture(personAges));
}};
dao.create(new Person("John", 10));
assertEquals(1, personsCreated.size());
Person first = personsCreated.get(0);
assertEquals("John", first.getName());
assertEquals(10, first.getAge());
dao.create(new Person("Jane", 20));
assertEquals(2, personsCreated.size());
Person second = personsCreated.get(1);
assertEquals("Jane", second.getName());
assertEquals(20, second.getAge());
dao.create("Mary Jane", 35);
assertEquals(1, personNames.size());
assertEquals("Mary Jane", personNames.get(0));
assertEquals(1, personAges.size());
assertEquals(35, personAges.get(0).intValue());
}
@Test
public void captureArgumentsIntoListInVerificationBlock()
{
dao.create(new Person("John", 10));
dao.create("Mary Jane", 35);
dao.create("", 56);
dao.create(new Person("Jane", 20));
dao.create("Daisy Jones", 6);
new Verifications() {
final List<Person> created = new ArrayList<Person>();
final List<Integer> ages = new ArrayList<Integer>();
{
dao.create("", withCapture(ages));
assertEquals(singletonList(56), ages);
dao.create(withCapture(created));
assertEquals(2, created.size());
Person first = created.get(0);
assertEquals("John", first.getName());
assertEquals(10, first.getAge());
Person second = created.get(1);
assertEquals("Jane", second.getName());
assertEquals(20, second.getAge());
ages.clear();
dao.create(withSubstring(" "), withCapture(ages)); times = 2;
assertEquals(asList(35, 6), ages);
}
};
}
@Test
public void captureNewedInstance(@Mocked Person mockedPerson)
{
Person p = new Person();
dao.create(p);
new Verifications() {{
Person newInstance = withCapture(new Person()).get(0);
Person capturedPerson;
dao.create(capturedPerson = withCapture());
assertSame(newInstance, capturedPerson);
}};
}
@Test
public void captureMultipleNewInstances(@Mocked Person mockedPerson)
{
dao.create(new Person("Paul", 10));
dao.create(new Person("Mary", 15));
dao.create(new Person("Joe", 20));
new Verifications() {{
List<Person> personsInstantiated = withCapture(new Person(anyString, anyInt));
List<Person> personsCreated = new ArrayList<Person>();
dao.create(withCapture(personsCreated));
assertEquals(personsInstantiated, personsCreated);
}};
}
@Test
public void attemptToCaptureNewInstanceWhenThereWasNone(@Mocked Person mockedPerson)
{
thrown.expect(MissingInvocation.class);
thrown.expectMessage("Person(any String, any int)");
dao.create("test", 14);
new Verifications() {{
List<Person> newInstances = withCapture(new Person());
times = 0;
assertTrue(newInstances.isEmpty());
withCapture(new Person(anyString, anyInt));
}};
}
@Test
public void captureTwoSetsOfNewInstancesOfTheSameType(@Mocked Person mockedPerson)
{
// First set.
final Person p1 = new Person();
// Second set.
final Person p2 = new Person("Paul", 10);
final Person p3 = new Person("Mary", 15);
new Verifications() {{
List<Person> persons1 = withCapture(new Person(anyString, anyInt));
assertEquals(asList(p2, p3), persons1);
List<Person> persons2 = withCapture(new Person());
assertEquals(singletonList(p1), persons2);
}};
}
@Test
public void captureNewInstancesAfterVerifyingNewInstanceOfDifferentType(@Mocked Person mockedPerson)
{
new PersonDAO();
final Person p1 = new Person("Paul", 10);
final Person p2 = new Person("Mary", 10);
new Verifications() {{
new PersonDAO();
List<Person> persons = withCapture(new Person(anyString, 10));
assertEquals(asList(p1, p2), persons);
}};
}
@Test
public void attemptToCaptureArgumentForInvocationThatNeverOccurred_unordered()
{
thrown.expect(MissingInvocation.class);
thrown.expectMessage("Missing 1 invocation to:");
thrown.expectMessage("PersonDAO#create(");
thrown.expectMessage("any " + Person.class.getName());
new Verifications() {{
Person p;
dao.create(p = withCapture());
times = 1;
assertEquals("...", p.getName());
}};
}
@Test
public void attemptToCaptureArgumentForInvocationThatNeverOccurred_ordered()
{
thrown.expect(MissingInvocation.class);
new VerificationsInOrder() {{
Person p;
dao.create(p = withCapture());
times = 1;
assertEquals("...", p.getName());
}};
}
static class ClassWithVarargsMethod { @SuppressWarnings("unused") void varargsMethod(String s, String... values) {} }
@Test
public void captureVarargsValuesFromAllInvocations(@Mocked final ClassWithVarargsMethod mock)
{
final String[] expectedValues1 = {"a", "b"};
final String[] expectedValues2 = {"1", "2"};
mock.varargsMethod("First", expectedValues1);
mock.varargsMethod("Second", expectedValues2);
new Verifications() {{
List<String> capturedNames = new ArrayList<String>();
List<String[]> capturedValues = new ArrayList<String[]>();
mock.varargsMethod(withCapture(capturedNames), withCapture(capturedValues));
assertEquals(asList("First", "Second"), capturedNames);
assertArrayEquals(expectedValues1, capturedValues.get(0));
assertArrayEquals(expectedValues2, capturedValues.get(1));
}};
}
@Test
public void captureArgumentsIntoAListOfASubtypeOfTheCapturedParameterType() {
final List<Integer> expectedValues = asList(1, 3);
dao.doSomethingElse(1);
dao.doSomethingElse(2.0);
dao.doSomethingElse(3);
new Verifications() {{
List<Integer> onlyIntegers = new ArrayList<Integer>();
dao.doSomethingElse(withCapture(onlyIntegers));
assertEquals(expectedValues, onlyIntegers);
}};
}
@Test
public void captureListArgumentsFromMultipleInvocations()
{
final List<Integer> integers1 = asList(1, 2, 3);
final List<Integer> integers2 = asList(4, 5);
dao.doSomething(integers1);
dao.doSomething(integers2);
new Verifications() {{
List<List<Integer>> captures = new ArrayList<List<Integer>>();
dao.doSomething(withCapture(captures));
assertEquals(integers1, captures.get(0));
assertEquals(integers2, captures.get(1));
}};
}
}