/*
* Copyright Unitils.org
*
* 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.
*/
package org.unitils.mock.argumentmatcher;
import org.junit.Before;
import org.junit.Test;
import org.unitils.core.UnitilsException;
import org.unitils.mock.MockUnitils;
import org.unitils.mock.core.MockObject;
import org.unitils.mock.mockbehavior.MockBehavior;
import java.lang.reflect.Method;
import java.util.List;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertTrue;
import static org.unitils.mock.ArgumentMatchers.notNull;
import static org.unitils.mock.argumentmatcher.ArgumentMatcherPositionFinder.getArgumentMatcherIndexes;
import static org.unitils.reflectionassert.ReflectionAssert.assertReflectionEquals;
import static org.unitils.util.ReflectionUtils.getMethod;
/**
* Tests the finding of the argument matchers in a proxy method invocation.
*
* @author Tim Ducheyne
* @author Filip Neven
* @author Kenny Claes
*/
public class ArgumentMatcherPositionFinderTest {
/* The line nrs of the proxy method invocations in the TestClass.test method */
private int invocationLineNr = 171;
private int noMatcherInvocationLineNr = invocationLineNr + 2;
private int twoSameInvocationsOnSameLineLineNr = invocationLineNr + 4;
private int twoDifferentInvocationsOnSameLineLineNr = invocationLineNr + 6;
private int multiLineInvocationLineNrFrom = invocationLineNr + 8;
private int multiLineInvocationLineNrTo = invocationLineNr + 10;
private int noArgumentsInvocationLineNr = invocationLineNr + 12;
private int nestedMethodInvocationLineNr = invocationLineNr + 14;
/* A regular target method on the proxy */
private Method proxyMethod;
/* A static target method on the proxy */
private Method staticProxyMethod;
/* A target method without args on the proxy */
private Method noArgumentsProxyMethod;
private Method valueReturningProxyMethod;
/**
* Initializes the proxy methods and mock object
*/
@Before
public void setUp() {
proxyMethod = getMethod(MockedClass.class, "someMethod", false, String.class, String.class, String.class);
staticProxyMethod = getMethod(MockedClass.class, "someStaticMethod", true, Integer.TYPE, Integer.TYPE);
noArgumentsProxyMethod = getMethod(MockedClass.class, "someMethod", false);
valueReturningProxyMethod = getMethod(MockedClass.class, "valueReturningMethod", false, String.class, String.class, String.class);
}
/**
* Test finding matchers for a proxy method invocation with the first and third arguments being an argument matcher.
*/
@Test
public void testGetArgumentMatcherIndexes() {
List<Integer> result = getArgumentMatcherIndexes(TestClass.class, "test", proxyMethod, invocationLineNr, invocationLineNr, 1);
assertReflectionEquals(asList(0, 2), result);
}
/**
* Test finding matchers for a proxy method invocation without argument matcher.
*/
@Test
public void noArgumentMatchers() {
List<Integer> result = getArgumentMatcherIndexes(TestClass.class, "test", proxyMethod, noMatcherInvocationLineNr, noMatcherInvocationLineNr, 1);
assertTrue(result.isEmpty());
}
/**
* Test finding matchers for a proxy method that has no arguments.
*/
@Test
public void noArguments() {
List<Integer> result = getArgumentMatcherIndexes(TestClass.class, "test", noArgumentsProxyMethod, noArgumentsInvocationLineNr, noArgumentsInvocationLineNr, 1);
assertTrue(result.isEmpty());
}
@Test
public void twoInvocationsWithSameNameOnSameLine_first() {
List<Integer> result = getArgumentMatcherIndexes(TestClass.class, "test", proxyMethod, twoSameInvocationsOnSameLineLineNr, twoSameInvocationsOnSameLineLineNr, 1);
assertReflectionEquals(asList(0), result);
}
@Test
public void twoInvocationsWithSameNameOnSameLine_last() {
List<Integer> result = getArgumentMatcherIndexes(TestClass.class, "test", proxyMethod, twoSameInvocationsOnSameLineLineNr, twoSameInvocationsOnSameLineLineNr, 2);
assertReflectionEquals(asList(2), result);
}
@Test
public void twoInvocationsWithDifferentNameOnSameLine_first() {
List<Integer> result = getArgumentMatcherIndexes(TestClass.class, "test", proxyMethod, twoDifferentInvocationsOnSameLineLineNr, twoDifferentInvocationsOnSameLineLineNr, 1);
assertReflectionEquals(asList(0), result);
}
@Test
public void twoInvocationsWithDifferentNameOnSameLine_last() {
List<Integer> result = getArgumentMatcherIndexes(TestClass.class, "test", valueReturningProxyMethod, twoDifferentInvocationsOnSameLineLineNr, twoDifferentInvocationsOnSameLineLineNr, 1);
assertReflectionEquals(asList(2), result);
}
@Test
public void invocationOnMultipleLines() {
List<Integer> result = getArgumentMatcherIndexes(TestClass.class, "test", proxyMethod, multiLineInvocationLineNrFrom, multiLineInvocationLineNrTo, 1);
assertReflectionEquals(asList(0, 2), result);
}
@Test(expected = UnitilsException.class)
public void argumentMatcherInAnExpression() {
getArgumentMatcherIndexes(TestClass.class, "test", valueReturningProxyMethod, nestedMethodInvocationLineNr, nestedMethodInvocationLineNr, 1);
}
@Test(expected = UnitilsException.class)
public void wrongMethodName() {
getArgumentMatcherIndexes(TestClass.class, "xxxx", proxyMethod, invocationLineNr, invocationLineNr, 1);
}
@Test(expected = UnitilsException.class)
public void indexNotFound() {
getArgumentMatcherIndexes(TestClass.class, "test", proxyMethod, invocationLineNr, invocationLineNr, 99);
}
/**
* Test class with 5 proxy method invocations.
*/
public static class TestClass {
private MockObject<MockedClass> mockObject = new MockObject<MockedClass>("testMock", MockedClass.class, this);
private MockBehavior dummyBehavior = MockUnitils.createDummy(MockBehavior.class);
public void test() {
// regular invocation
mockObject.performs(dummyBehavior).someMethod(notNull(String.class), "aValue", notNull(String.class));
// invocation without argument matchers
mockObject.performs(dummyBehavior).someMethod("aValue", "aValue", "aValue");
// 2 same invocations on same line DO NOT FORMAT
mockObject.performs(dummyBehavior).someMethod(notNull(String.class), "aValue", "aValue");mockObject.performs(dummyBehavior).someMethod("aValue", "aValue", notNull(String.class));
// 2 different invocations on same line DO NOT FORMAT
mockObject.performs(dummyBehavior).someMethod(notNull(String.class), "aValue", "aValue");mockObject.performs(dummyBehavior).valueReturningMethod("aValue", "aValue", notNull(String.class));
// Invocation spread over multiple lines
mockObject.performs(dummyBehavior).someMethod(notNull(String.class),
"aValue",
notNull(String.class));
// no arguments invocation
mockObject.performs(dummyBehavior).someMethod();
// method also used inside argument expression
mockObject.performs(dummyBehavior).valueReturningMethod(notNull(String.class), new MockedClass().valueReturningMethod(null, null, null), "aValue");
}
}
/**
* Simulates a proxy
*/
public static class MockedClass {
public void someMethod(String param1, String param2, String param3) {
}
public static void someStaticMethod(int param1, int param2) {
}
public void someMethod() {
}
public String valueReturningMethod(String param1, String param2, String param3) {
return null;
}
}
}