/*
* Copyright (c) 2006 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import java.io.*;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.*;
import static java.util.Arrays.asList;
import org.junit.*;
import static org.junit.Assert.*;
public final class GenericMockedTypesTest
{
@Mocked Callable<Integer> mock2;
@Test
public void mockGenericInterfaces(@Mocked final Callable<?> mock1) throws Exception
{
new Expectations() {{
mock1.call(); result = "mocked";
mock2.call(); result = 123;
}};
assertEquals("mocked", mock1.call());
assertEquals(123, mock2.call().intValue());
}
@Test
public void obtainGenericSuperclassFromClassGeneratedForNonGenericInterface(@Mocked Runnable mock)
{
Class<?> generatedClass = mock.getClass();
Type genericSuperClass = generatedClass.getGenericSuperclass();
// At one time, a "GenericSignatureFormatError: Signature Parse error: expected a class type
// Remaining input: nullLjava/lang/Runnable;" would occur.
assertSame(Object.class, genericSuperClass);
}
@Test
public void mockGenericAbstractClass(@Mocked final Dictionary<Integer, String> mock) throws Exception
{
new Expectations() {{
mock.put(123, "test"); result = "mocked";
}};
assertEquals("mocked", mock.put(123, "test"));
}
@Test
public void mockRawMapInterface(@SuppressWarnings("rawtypes") @Mocked final Map rawMap)
{
new Expectations() {{
rawMap.get("test");
result = new Object();
}};
Object value = rawMap.get("test");
assertNotNull(value);
}
public interface InterfaceWithMethodParametersMixingGenericTypesAndArrays
{
<T> void doSomething(int[] i, T b);
void doSomething(Callable<int[]> pc, int[] ii);
void doSomething(Callable<String> pc, int[] i, boolean[] currencies, int[] ii);
}
@Test
public void mockMethodsHavingGenericsAndArrays(@Mocked InterfaceWithMethodParametersMixingGenericTypesAndArrays mock)
{
mock.doSomething((Callable<int[]>) null, new int[] {1, 2});
mock.doSomething(null, new int[] {1, 2}, null, new int[] {3, 4, 5});
}
public interface NonGenericInterfaceWithGenericMethods
{
<T> T genericMethodWithUnboundedReturnType();
<T extends CharSequence> T genericMethodWithBoundedReturnType();
}
@Test
public void resultFromGenericMethodsOfNonGenericInterface(@Mocked final NonGenericInterfaceWithGenericMethods mock)
{
new Expectations() {{
mock.genericMethodWithUnboundedReturnType(); result = 123;
mock.genericMethodWithBoundedReturnType(); result = "test";
}};
Object v1 = mock.genericMethodWithUnboundedReturnType();
assertEquals(123, v1);
Object v2 = mock.genericMethodWithBoundedReturnType();
assertEquals("test", v2);
}
static class Item implements Serializable {}
static class GenericContainer<T extends Serializable> { final T getItem() { return null; } }
@Test
public void createFirstLevelCascadedMockFromTypeParameter(@Mocked GenericContainer<Item> mockContainer)
{
Serializable mock = mockContainer.getItem();
assertSame(Item.class, mock.getClass());
}
static class Factory1 { static GenericContainer<Item> getContainer() { return null; } }
@Test
public void createSecondLevelCascadedMockFromTypeParameterInGenericMethodResolvedFromFirstLevelReturnType(
@Mocked Factory1 mockFactory)
{
GenericContainer<Item> mockContainer = Factory1.getContainer();
Serializable cascadedMock = mockContainer.getItem();
assertNotNull(cascadedMock);
assertSame(Item.class, cascadedMock.getClass());
}
static class ConcreteContainer extends GenericContainer<Item> {}
static class Factory2 { ConcreteContainer getContainer() { return null; } }
@Test
public void createSecondLevelCascadedMockFromTypeParameterInBaseTypeOfMethodReturn(@Mocked Factory2 mockFactory)
{
ConcreteContainer mockContainer = mockFactory.getContainer();
Serializable cascadedMock = mockContainer.getItem();
assertSame(Item.class, cascadedMock.getClass());
}
static class Collaborator { Runnable doSomething() { return null; } }
static class Collaborator2 {}
@Test
public void cascadingClassWithNameStartingWithAnotherMockedClass(
@Mocked final Collaborator regularMock, @Mocked Collaborator2 cascadingMock)
{
new Expectations() {{
regularMock.doSomething();
}};
assertNotNull(regularMock.doSomething());
}
public interface InterfaceWithBoundedTypeParameter<T extends Runnable> { T getFoo(); }
@Test
public void createCascadedMockFromGenericInterfaceMethodWhichReturnsBoundedTypeParameter(
@Mocked InterfaceWithBoundedTypeParameter<?> mock)
{
Runnable foo = mock.getFoo();
assertNotNull(foo);
foo.run();
}
public interface InterfaceWhichExtendsInterfaceWithBoundedTypeParameter<T extends Runnable>
extends InterfaceWithBoundedTypeParameter<T> {}
@Test
public void createCascadedMockFromGenericMethodDefinedInSuperInterfaceWithBoundedTypeParameter(
@Mocked InterfaceWhichExtendsInterfaceWithBoundedTypeParameter<?> mock)
{
Runnable foo = mock.getFoo();
assertNotNull(foo);
foo.run();
}
static class Abc {}
static class GenericBase<T> { T doSomething() { return null; } }
static class GenericSubclass<T> extends GenericBase<T> { T getAbc() { return null; } }
@Test
public void createCascadedMockFromGenericSubclassHavingSameTypeParameterNameAsBaseClass(
@Mocked GenericSubclass<Abc> mock)
{
Abc abc = mock.getAbc();
assertNotNull(abc);
}
@Test
public void mockGenericClassHavingTypeArgumentOfArrayType(@Mocked GenericBase<String[]> mock)
{
String[] result = mock.doSomething();
assertEquals(0, result.length);
}
@Test
public void mockGenericClassHavingTypeArgumentOfArrayTypeWithPrimitiveComponent(@Mocked GenericBase<int[]> mock)
{
int[] result = mock.doSomething();
assertEquals(0, result.length);
}
@Test
public void mockGenericClassHavingTypeArgumentOfArrayTypeWith2DPrimitiveComponent(@Mocked GenericBase<int[][]> mock)
{
int[][] result = mock.doSomething();
assertEquals(0, result.length);
}
@Test
public void mockGenericClassHavingTypeArgumentOfArrayTypeWithGenericComponent(@Mocked GenericBase<List<?>[]> mock)
{
List<?>[] result = mock.doSomething();
assertEquals(0, result.length);
}
static final class DerivedClass extends GenericBase<Number[]> {}
@Test
public void mockClassExtendingAGenericBaseClassHavingTypeArgumentOfArrayType(@Mocked DerivedClass mock)
{
Number[] result = mock.doSomething();
assertEquals(0, result.length);
}
public interface BaseGenericInterface<V> { V doSomething(); }
public interface DerivedGenericInterface<V> extends BaseGenericInterface<List<V>> { V doSomethingElse(); }
@Test
public void recordGenericInterfaceMethodWithReturnTypeGivenByTypeParameterDependentOnAnotherTypeParameterOfSameName(
@Mocked final DerivedGenericInterface<String> dep) throws Exception
{
final List<String> values = asList("a", "b");
new Expectations() {{
dep.doSomething(); result = values;
dep.doSomethingElse(); result = "Abc";
}};
List<String> resultFromBase = dep.doSomething();
String resultFromSub = dep.doSomethingElse();
assertSame(values, resultFromBase);
assertEquals("Abc", resultFromSub);
}
@Test
public void mockGenericTypeWithGenericMultiDimensionalArrayTypeArgument(@Mocked GenericBase<List<?>[][]> mock)
{
List<?>[][] result = mock.doSomething();
assertEquals(0, result.length);
}
public interface BaseInterface<T> { void doSomething(T t); }
public interface SubInterface extends BaseInterface<String> { @Override void doSomething(String s); }
@Test
public void invokeGenericBaseInterfaceMethodThatIsOverriddenInMockedSubInterface(@Mocked final SubInterface mock)
{
@SuppressWarnings("UnnecessaryLocalVariable") BaseInterface<String> base = mock;
base.doSomething("test");
new Verifications() {{ mock.doSomething("test"); }};
}
public static class Outer<T>
{
public abstract class Inner { public abstract T getSomeValue(); }
public abstract class SubInner extends Inner {}
}
@Test
public void mockInnerClassWhichUsesTypeVariableOfOuterClass(@Mocked Outer<String>.Inner mock)
{
String in = mock.getSomeValue();
assertNull(in);
}
@Test
public void mockAbstractSubClassOfInnerClassWhichUsesTypeVariableOfOuterClass(@Mocked Outer<String>.SubInner mock)
{
String in = mock.getSomeValue();
assertNull(in);
}
static class T1 {}
static class T2 {}
@Test
public void cascadeFromGenericMethodOfSecondMockedGenericTypeHavingDifferentParameterTypeFromFirstMockedType(
@Mocked GenericBase<T1> mock1, @Mocked GenericBase<T2> mock2)
{
T2 r = mock2.doSomething();
assertNotNull(r);
}
}