/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit; import java.util.*; import static java.util.Arrays.asList; import org.junit.*; import org.junit.rules.*; import static org.junit.Assert.*; import mockit.internal.*; public final class ExpectationsWithVarArgsMatchersTest { @Rule public final ExpectedException thrown = ExpectedException.none(); static class Collaborator { List<?> complexOperation(Object input1, Object... otherInputs) { return input1 == null ? Collections.emptyList() : asList(otherInputs); } @SuppressWarnings("UnusedDeclaration") int anotherOperation(int i, boolean b, String s, String... otherStrings) { return -1; } boolean doSomething(int i, Object... values) { return i + values.length > 0; } } public interface Dependency { void doSomething(String... args); } @Mocked Collaborator mock; @Mocked Dependency mock2; @Test public void replayVarargsMethodWithDifferentThanExpectedNonVarargsArgument() { thrown.expect(UnexpectedInvocation.class); new StrictExpectations() {{ mock.complexOperation(1, 2, 3); }}; mock.complexOperation(2, 2, 3); } @Test public void replayVarargsMethodWithDifferentThanExpectedNumberOfVarargsArguments_strict() { thrown.expect(UnexpectedInvocation.class); new StrictExpectations() {{ mock.complexOperation(1, 2, 3); }}; mock.complexOperation(1, 2); } @Test public void replayVarargsMethodWithDifferentThanExpectedNumberOfVarargsArguments() { thrown.expect(MissingInvocation.class); new Expectations() {{ mock2.doSomething("1", "2", "3"); times = 1; }}; mock2.doSomething("1", "2"); } @Test public void replayVarargsMethodWithDifferentThanExpectedVarargsArgument_strict() { thrown.expect(UnexpectedInvocation.class); new StrictExpectations() {{ mock.complexOperation(1, 2, 3); }}; mock.complexOperation(1, 2, 4); } @Test public void replayVarargsMethodWithDifferentThanExpectedVarargsArgument() { thrown.expect(MissingInvocation.class); new Expectations() {{ mock2.doSomething("1", "2", "3"); }}; mock2.doSomething("1", "2", "4"); } @Test public void expectInvocationOnMethodWithVarargsArgumentUsingArgumentMatchers() { new Expectations() {{ mock.complexOperation(withEqual(1), withNotEqual(2), withNull()); mock2.doSomething(withPrefix("C"), withSuffix(".")); }}; mock.complexOperation(1, 3, null); mock2.doSomething("Cab", "123."); } @Test public void expectInvocationWithAnyNumberOfVariableArguments() { new StrictExpectations() {{ mock.complexOperation(any, (Object[]) null); times = 3; mock2.doSomething((String[]) any); minTimes = 2; mock.complexOperation(123, (Object[]) any); }}; mock.complexOperation("test"); mock.complexOperation(null, 'X'); mock.complexOperation(1, 3, null); mock2.doSomething(); mock2.doSomething("test", "abc"); mock.complexOperation(123, true, "test", 3); } @Test public void expectInvocationsWithMatcherForVarargsParameterOnly() { final List<Integer> values = asList(1, 2, 3); new Expectations() {{ mock.complexOperation("test", (Object[]) any); result = values; mock.anotherOperation(1, true, null, (String[]) any); result = 123; mock.doSomething(anyInt, (Object[]) any); result = true; }}; assertSame(values, mock.complexOperation("test", true, 'a', 2.5)); assertSame(values, mock.complexOperation("test", 123)); assertSame(values, mock.complexOperation("test")); assertEquals(123, mock.anotherOperation(1, true, null)); assertEquals(123, mock.anotherOperation(1, true, null, "A", null, "b")); assertEquals(123, mock.anotherOperation(1, true, "test", "a", "b")); assertTrue(mock.doSomething(-1)); assertTrue(mock.doSomething(-2, "test")); } @Test public void expectInvocationOnVarargsMethodWithMatcherOnlyForRegularFirstParameter() { new Expectations() {{ mock.complexOperation(any, 1, 2); }}; mock.complexOperation("test", 1, 2); } @Test public void expectInvocationWithMatchersForRegularParametersAndAllVarargsValues() { new Expectations() {{ mock.complexOperation(anyBoolean, anyInt, withEqual(2)); mock.complexOperation(anyString, withEqual(1), any, withEqual(3), anyBoolean); }}; mock.complexOperation(true, 1, 2); mock.complexOperation("abc", 1, 2, 3, true); } @Test public void recordExpectationsWithMatchersForSomeRegularParametersAndNoneForVarargs() { new Expectations() {{ mock.anotherOperation(1, anyBoolean, "test", "a"); result = 1; mock.anotherOperation(anyInt, true, withSubstring("X"), "a", "b"); result = 2; }}; // Invocations that match a recorded expectation: assertEquals(1, mock.anotherOperation(1, true, "test", "a")); assertEquals(1, mock.anotherOperation(1, true, "test", "a")); assertEquals(1, mock.anotherOperation(1, false, "test", "a")); assertEquals(2, mock.anotherOperation(2, true, "aXb", "a", "b")); assertEquals(2, mock.anotherOperation(-1, true, " X", "a", "b")); assertEquals(2, mock.anotherOperation(0, true, "XXX", "a", "b")); assertEquals(2, mock.anotherOperation(1, true, "X", "a", "b")); // Invocations that don't match any expectation: assertEquals(0, mock.anotherOperation(1, false, "test", null, "a")); assertEquals(0, mock.anotherOperation(1, false, "tst", "a")); assertEquals(0, mock.anotherOperation(0, false, "test", "a")); assertEquals(0, mock.anotherOperation(1, true, "test", "b")); assertEquals(0, mock.anotherOperation(1, true, "test")); assertEquals(0, mock.anotherOperation(2, false, "aXb", "a", "b")); assertEquals(0, mock.anotherOperation(1, true, " X", "A", "b")); assertEquals(0, mock.anotherOperation(0, true, "XXX", "a")); assertEquals(0, mock.anotherOperation(0, true, "XXX", "b")); assertEquals(0, mock.anotherOperation(32, true, "-Xx", "a", null)); } @Test public void expectInvocationsWithNonNullRegularArgumentAndAnyVarargs() { new Expectations() {{ mock.complexOperation(withNotNull(), (Object[]) any); times = 3; }}; mock.complexOperation(new Object(), 1, "2"); mock.complexOperation("", true, 'a', 2.5); mock.complexOperation(123); } @Test public void expectInvocationWithNonNullRegularArgumentAndAnyVarargsButReplayWithNull() { thrown.expect(UnexpectedInvocation.class); new StrictExpectations() {{ mock.complexOperation(withNotNull(), (Object[]) any); }}; mock.complexOperation(null, 1, "2"); } @Test public void expectInvocationWithMatchersForSomeRegularParametersAndAllForVarargs() { new Expectations() {{ mock.anotherOperation(anyInt, true, withEqual("abc"), anyString, withEqual("test")); result = 1; mock.anotherOperation(0, anyBoolean, withEqual("Abc"), anyString, anyString, anyString); result = 2; }}; assertEquals(0, mock.anotherOperation(1, false, "test", null, "a")); assertEquals(1, mock.anotherOperation(2, true, "abc", "xyz", "test")); assertEquals(1, mock.anotherOperation(-1, true, "abc", null, "test")); assertEquals(0, mock.anotherOperation(-1, true, "abc", null, "test", null)); assertEquals(2, mock.anotherOperation(0, false, "Abc", "", "Abc", "test")); assertEquals(0, mock.anotherOperation(0, false, "Abc", "", "Abc", "test", "")); } @SuppressWarnings("unused") static class VarArgs { public void varsOnly(int... ints) {} public void mixed(String arg0, int... ints) {} } @SuppressWarnings("NullArgumentToVariableArgMethod") @Test public void expectInvocationWithNoVarArgs(@Mocked final VarArgs varargs) { new StrictExpectations() {{ varargs.varsOnly(); times = 2; varargs.mixed("abcd"); times = 2; }}; varargs.varsOnly(); varargs.varsOnly(null); varargs.mixed("abcd"); varargs.mixed("abcd", null); } static class ReferenceVarArgs { @SuppressWarnings("unused") public void mixed(String[] strings, Integer... ints) {} } @Test public void expectInvocationWithNonPrimitiveVarArgs(@Mocked final ReferenceVarArgs varargs) { final String[] strings1 = new String[0]; final String[] strings2 = {"efgh", "ijkl"}; new Expectations() {{ varargs.mixed(null, 4, 5, 6); varargs.mixed(strings1, 4, 5, 6); varargs.mixed(strings2, 4, 5, 6); varargs.mixed(null); varargs.mixed(strings1); varargs.mixed(strings2); }}; varargs.mixed(null, 4, 5, 6); varargs.mixed(strings1, 4, 5, 6); varargs.mixed(strings2, 4, 5, 6); varargs.mixed(null); varargs.mixed(strings1); varargs.mixed(strings2); } @SuppressWarnings("unused") static class PrimitiveVarArgs { public void varsOnly(int... ints) {} public void mixed(String arg0, String[] strings, int... ints) {} } @SuppressWarnings("NullArgumentToVariableArgMethod") @Test public void expectInvocationWithPrimitiveVarArgs(@Mocked final PrimitiveVarArgs varargs) { final String[] strings1 = new String[0]; final String[] strings2 = {"efgh", "ijkl"}; new StrictExpectations() {{ varargs.varsOnly(1, 2, 3); varargs.varsOnly(null); varargs.mixed("abcd", null, 4, 5, 6); varargs.mixed("abcd", strings1, 4, 5, 6); varargs.mixed("abcd", strings2, 4, 5, 6); varargs.mixed("abcd", null); varargs.mixed("abcd", strings1); varargs.mixed("abcd", strings2); varargs.mixed("abcd", null, null); varargs.mixed(null, null, null); }}; varargs.varsOnly(1, 2, 3); varargs.varsOnly(null); varargs.mixed("abcd", null, 4, 5, 6); varargs.mixed("abcd", strings1, 4, 5, 6); varargs.mixed("abcd", strings2, 4, 5, 6); varargs.mixed("abcd", null); varargs.mixed("abcd", strings1); varargs.mixed("abcd", strings2); varargs.mixed("abcd", null, null); varargs.mixed(null, null, null); } static class MixedVarArgs { @SuppressWarnings("unused") public void mixed(String[] strings, int... ints) {} } @Test public void expectInvocationWithPrimitiveVarArgsUsingMatchers(@Mocked final MixedVarArgs varargs) { final String[] strings1 = new String[0]; final String[] strings2 = {"efgh", "ijkl"}; new Expectations() {{ varargs.mixed((String[]) withNull(), withEqual(4), withEqual(5), withEqual(6)); varargs.mixed(withEqual(strings1), withEqual(4), withEqual(5), withEqual(6)); varargs.mixed(withEqual(strings2), withEqual(4), withEqual(5), withEqual(6)); varargs.mixed((String[]) withNull()); varargs.mixed(withEqual(strings1)); varargs.mixed(withEqual(strings2)); }}; varargs.mixed(null, 4, 5, 6); varargs.mixed(strings1, 4, 5, 6); varargs.mixed(strings2, 4, 5, 6); varargs.mixed(null); varargs.mixed(strings1); varargs.mixed(strings2); } @Test public void expectInvocationWithMatchersForAllParametersAndVarargsValuesButReplayWithDifferentVarargValue() { thrown.expect(UnexpectedInvocation.class); new StrictExpectations() {{ mock.complexOperation(anyString, anyBoolean, withEqual(123L)); }}; mock.complexOperation("abc", true, 1L); } @Test public void expectationRecordedWithNotNullMatcherForVarargsParameter() { new Expectations() {{ mock.doSomething(0, (Object[]) withNotNull()); result = true; }}; assertTrue(mock.doSomething(0, "test")); //noinspection NullArgumentToVariableArgMethod assertFalse(mock.doSomething(0, (Object[]) null)); } }