From 8da3e6ec64b991f5aa1e6561941d130683eba753 Mon Sep 17 00:00:00 2001 From: Luis Sigal Date: Thu, 24 Feb 2011 17:22:33 +0000 Subject: Add android-mock to external Android mock is used by QuickSearchBox to mock classes instead of creating tons of interfaces. Change-Id: Ib53ca3a6c5e8e27f42b66cc9e39bbf0d55ed2170 --- .../mocking/AndroidFrameworkMockGeneratorTest.java | 165 ++++ .../testing/mocking/AndroidMockGeneratorTest.java | 575 +++++++++++++ .../android/testing/mocking/AndroidMockTest.java | 927 +++++++++++++++++++++ .../mocking/ClassDoesWorkInConstructor.java | 77 ++ .../testing/mocking/ClassHasDelegateMethods.java | 38 + .../testing/mocking/ClassHasFinalMethods.java | 35 + .../mocking/ClassHasNoDefaultConstructor.java | 31 + .../mocking/ClassHasNoPublicConstructors.java | 27 + .../testing/mocking/ClassHasOverloadedMethods.java | 30 + .../testing/mocking/ClassHasStaticMethods.java | 31 + .../android/testing/mocking/ClassIsAnnotation.java | 25 + .../android/testing/mocking/ClassIsEnum.java | 25 + .../android/testing/mocking/ClassIsFinal.java | 27 + .../android/testing/mocking/ClassIsInterface.java | 25 + .../android/testing/mocking/ClassTypeTests.java | 269 ++++++ .../testing/mocking/ConstructorCreationTests.java | 131 +++ .../android/testing/mocking/FileUtilsTest.java | 70 ++ .../android/testing/mocking/SdkVersionTest.java | 75 ++ .../testing/mocking/UsesMocksProcessorTest.java | 275 ++++++ 19 files changed, 2858 insertions(+) create mode 100644 tests/com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest.java create mode 100644 tests/com/google/android/testing/mocking/AndroidMockGeneratorTest.java create mode 100644 tests/com/google/android/testing/mocking/AndroidMockTest.java create mode 100644 tests/com/google/android/testing/mocking/ClassDoesWorkInConstructor.java create mode 100644 tests/com/google/android/testing/mocking/ClassHasDelegateMethods.java create mode 100644 tests/com/google/android/testing/mocking/ClassHasFinalMethods.java create mode 100644 tests/com/google/android/testing/mocking/ClassHasNoDefaultConstructor.java create mode 100644 tests/com/google/android/testing/mocking/ClassHasNoPublicConstructors.java create mode 100644 tests/com/google/android/testing/mocking/ClassHasOverloadedMethods.java create mode 100644 tests/com/google/android/testing/mocking/ClassHasStaticMethods.java create mode 100644 tests/com/google/android/testing/mocking/ClassIsAnnotation.java create mode 100644 tests/com/google/android/testing/mocking/ClassIsEnum.java create mode 100644 tests/com/google/android/testing/mocking/ClassIsFinal.java create mode 100644 tests/com/google/android/testing/mocking/ClassIsInterface.java create mode 100644 tests/com/google/android/testing/mocking/ClassTypeTests.java create mode 100644 tests/com/google/android/testing/mocking/ConstructorCreationTests.java create mode 100644 tests/com/google/android/testing/mocking/FileUtilsTest.java create mode 100644 tests/com/google/android/testing/mocking/SdkVersionTest.java create mode 100644 tests/com/google/android/testing/mocking/UsesMocksProcessorTest.java (limited to 'tests/com/google/android/testing/mocking') diff --git a/tests/com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest.java b/tests/com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest.java new file mode 100644 index 0000000..813063f --- /dev/null +++ b/tests/com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest.java @@ -0,0 +1,165 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; + +import junit.framework.TestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Vector; +import java.util.jar.JarEntry; + +/** + * @author swoodward@google.com (Stephen Woodward) + */ +public class AndroidFrameworkMockGeneratorTest extends TestCase { + private void cleanupGeneratedClasses(CtClass... classes) { + for (CtClass clazz : classes) { + clazz.detach(); + } + } + + private Collection getMockJarEntries() { + JarEntry firstEntry = new JarEntry("java/lang/Object.class"); + JarEntry secondEntry = new JarEntry( + "com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest$Inner.class"); + List entryList = new ArrayList(); + entryList.add(firstEntry); + entryList.add(secondEntry); + return entryList; + } + + private void assertUnorderedContentsSame(Iterable expected, Iterable actual) { + List missingItems = new ArrayList(); + List extraItems = new ArrayList(); + for (T item : expected) { + missingItems.add(item); + } + for (T item : actual) { + missingItems.remove(item); + extraItems.add(item); + } + for (T item : expected) { + extraItems.remove(item); + } + if (missingItems.size() + extraItems.size() != 0) { + String errorMessage = + "Contents were different. Missing: " + Arrays.toString(missingItems.toArray()) + + " Extra: " + Arrays.toString(extraItems.toArray()); + fail(errorMessage); + } + } + + private List getClassNames(List classes) { + List classNames = new ArrayList(); + for (GeneratedClassFile clazz : classes) { + classNames.add(clazz.getClassName()); + } + return classNames; + } + + private AndroidFrameworkMockGenerator getMockGenerator() { + return new AndroidFrameworkMockGenerator(); + } + + public void testCreateMockForClass() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidFrameworkMockGenerator mockGenerator = getMockGenerator(); + for (SdkVersion version : SdkVersion.getAllVersions()) { + List classes = mockGenerator.createMocksForClass(Object.class, version); + + List expectedNames = new ArrayList(); + expectedNames.addAll(Arrays.asList(new String[] { + version.getPackagePrefix() + "genmocks.java.lang.ObjectDelegateSubclass", + version.getPackagePrefix() + "genmocks.java.lang.ObjectDelegateInterface"})); + List actualNames = getClassNames(classes); + assertUnorderedContentsSame(expectedNames, actualNames); + } + } + + public void testGetClassList() throws ClassNotFoundException { + Collection jarEntries = getMockJarEntries(); + List expectedClassNames = + new ArrayList(Arrays.asList(new String[] { + "java.lang.Object", + "com.google.android.testing.mocking.AndroidFrameworkMockGeneratorTest$Inner"})); + List> list = getMockGenerator().getClassList(jarEntries); + assertEquals(expectedClassNames.size(), list.size()); + for (Class clazz : list) { + assertTrue(clazz.getName(), expectedClassNames.contains(clazz.getName())); + } + } + + public void testIsClassFile() { + assertTrue(getMockGenerator().jarEntryIsClassFile(new JarEntry("something.class"))); + assertTrue(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.class"))); + assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.clas"))); + assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.class "))); + assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar"))); + } + + public void testGetJarFileNameForVersion() { + for (SdkVersion version : SdkVersion.getAllVersions()) { + getMockGenerator(); + assertEquals("lib/android/android_" + version.getVersionName() + ".jar", + AndroidFrameworkMockGenerator.getJarFileNameForVersion(version)); + } + } + + public void testGetMocksForClass() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List createdClasses = new ArrayList(); + AndroidFrameworkMockGenerator mockGenerator = getMockGenerator(); + for (SdkVersion version : SdkVersion.getAllVersions()) { + List createdMocks = mockGenerator.createMocksForClass( + Vector.class, version); + for (GeneratedClassFile mock : createdMocks) { + CtClass ctClass = ClassPool.getDefault().get(mock.getClassName()); + createdClasses.add(ctClass); + ctClass.toClass(); + } + } + List mocks = mockGenerator.getMocksForClass(Vector.class); + String[] expectedClassNames = new String[] { + "v15.genmocks.java.util.VectorDelegateSubclass", + "v15.genmocks.java.util.VectorDelegateInterface", + "v16.genmocks.java.util.VectorDelegateSubclass", + "v16.genmocks.java.util.VectorDelegateInterface", + "v201.genmocks.java.util.VectorDelegateSubclass", + "v201.genmocks.java.util.VectorDelegateInterface", + "v21.genmocks.java.util.VectorDelegateSubclass", + "v21.genmocks.java.util.VectorDelegateInterface", + "v22.genmocks.java.util.VectorDelegateSubclass", + "v22.genmocks.java.util.VectorDelegateInterface" + }; + assertEquals(expectedClassNames.length, mocks.size()); + for (int i = 0; i < mocks.size(); ++i) { + assertEquals(expectedClassNames[i], mocks.get(i).getClassName()); + } + cleanupGeneratedClasses(createdClasses.toArray(new CtClass[0])); + } + + class Inner { + } +} diff --git a/tests/com/google/android/testing/mocking/AndroidMockGeneratorTest.java b/tests/com/google/android/testing/mocking/AndroidMockGeneratorTest.java new file mode 100644 index 0000000..ef36b24 --- /dev/null +++ b/tests/com/google/android/testing/mocking/AndroidMockGeneratorTest.java @@ -0,0 +1,575 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.NotFoundException; + +import junit.framework.TestCase; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +/** + * Tests for the AndroidMockGenerator class. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class AndroidMockGeneratorTest extends TestCase { + private AndroidMockGenerator getAndroidMockGenerator() { + return new AndroidMockGenerator(); + } + + private NoFileAndroidMockGenerator getNoFileMockGenerator() { + return new NoFileAndroidMockGenerator(); + } + + private void cleanupGeneratedClasses(CtClass... classes) { + for (CtClass clazz : classes) { + clazz.detach(); + } + } + + private void assertUnorderedContentsSame(Iterable expected, Iterable actual) { + List missingItems = new ArrayList(); + List extraItems = new ArrayList(); + for (T item : expected) { + missingItems.add(item); + } + for (T item : actual) { + missingItems.remove(item); + extraItems.add(item); + } + for (T item : expected) { + extraItems.remove(item); + } + if (missingItems.size() + extraItems.size() != 0) { + String errorMessage = + "Contents were different. Missing: " + Arrays.toString(missingItems.toArray()) + + " Extra: " + Arrays.toString(extraItems.toArray()); + fail(errorMessage); + } + } + + private List getExpectedNamesForNumberClass() { + return getExpectedNamesForNumberClass(false); + } + + private List getExpectedNamesForObjectClass() { + List expectedNames = new ArrayList(); + expectedNames.addAll(Arrays.asList(new String[] {"clone", "finalize"})); + return expectedNames; + } + + private List getExpectedNamesForNumberClass(boolean includeDelegateMethods) { + List expectedNames = getExpectedNamesForObjectClass(); + expectedNames.addAll(Arrays.asList(new String[] {"byteValue", "doubleValue", "floatValue", + "intValue", "longValue", "shortValue"})); + if (includeDelegateMethods) { + expectedNames.addAll(Arrays.asList(new String[] {"getDelegate___AndroidMock", + "setDelegate___AndroidMock"})); + } + return expectedNames; + } + + private List getExpectedNamesForBigIntegerClass() { + List expectedNames = getExpectedNamesForNumberClass(); + expectedNames.addAll(Arrays.asList(new String[] {"abs", "add", "and", "andNot", "bitCount", + "bitLength", "clearBit", "compareTo", "divide", "divideAndRemainder", "flipBit", "gcd", + "getLowestSetBit", "isProbablePrime", "max", "min", "mod", "modInverse", "modPow", + "multiply", "negate", "nextProbablePrime", "not", "or", "pow", "remainder", "setBit", + "shiftLeft", "shiftRight", "signum", "subtract", "testBit", "toByteArray", "toString", + "xor"})); + return expectedNames; + } + + private List getMethodNames(CtMethod[] methods) { + List methodNames = new ArrayList(); + for (CtMethod method : methods) { + methodNames.add(method.getName()); + } + return methodNames; + } + + private List getClassNames(List classes) { + List classNames = new ArrayList(); + for (GeneratedClassFile clazz : classes) { + classNames.add(clazz.getClassName()); + } + return classNames; + } + + private List getExpectedSignaturesForBigIntegerClass() { + List expectedNames = new ArrayList(); + expectedNames.addAll(Arrays.asList(new String[] { + "public int java.math.BigInteger.getLowestSetBit()", + "public java.math.BigInteger java.math.BigInteger.abs()", + "protected void java.lang.Object.finalize() throws java.lang.Throwable", + "public java.math.BigInteger java.math.BigInteger.modPow(java.math.BigInteger," + + "java.math.BigInteger)", + "protected native java.lang.Object java.lang.Object.clone() throws " + + "java.lang.CloneNotSupportedException", + "public java.math.BigInteger java.math.BigInteger.setBit(int)", + "public java.math.BigInteger java.math.BigInteger.shiftRight(int)", + "public int java.math.BigInteger.bitLength()", + "public java.math.BigInteger java.math.BigInteger.not()", + "public java.math.BigInteger java.math.BigInteger.subtract(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.flipBit(int)", + "public boolean java.math.BigInteger.isProbablePrime(int)", + "public java.math.BigInteger java.math.BigInteger.add(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.modInverse(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.clearBit(int)", + "public java.math.BigInteger java.math.BigInteger.multiply(java.math.BigInteger)", + "public byte java.lang.Number.byteValue()", + "public java.math.BigInteger java.math.BigInteger.gcd(java.math.BigInteger)", + "public float java.math.BigInteger.floatValue()", + "public java.lang.String java.math.BigInteger.toString(int)", + "public java.math.BigInteger java.math.BigInteger.min(java.math.BigInteger)", + "public int java.math.BigInteger.intValue()", + "public java.math.BigInteger java.math.BigInteger.or(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.remainder(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.divide(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.xor(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.and(java.math.BigInteger)", + "public int java.math.BigInteger.signum()", + "public java.math.BigInteger[] java.math.BigInteger.divideAndRemainder(" + + "java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.max(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.shiftLeft(int)", + "public double java.math.BigInteger.doubleValue()", + "public java.math.BigInteger java.math.BigInteger.pow(int)", + "public short java.lang.Number.shortValue()", + "public java.math.BigInteger java.math.BigInteger.andNot(java.math.BigInteger)", + "public byte[] java.math.BigInteger.toByteArray()", + "public java.math.BigInteger java.math.BigInteger.negate()", + "public int java.math.BigInteger.compareTo(java.math.BigInteger)", + "public boolean java.math.BigInteger.testBit(int)", + "public int java.math.BigInteger.bitCount()", + "public long java.math.BigInteger.longValue()", + "public java.math.BigInteger java.math.BigInteger.mod(java.math.BigInteger)", + "public java.math.BigInteger java.math.BigInteger.nextProbablePrime()", + })); + return expectedNames; + } + + private List getMethodSignatures(Method[] methods) { + List methodSignatures = new ArrayList(); + for (Method method : methods) { + if (getAndroidMockGenerator().isMockable(method)) { + methodSignatures.add(method.toGenericString()); + } + } + return methodSignatures; + } + + public void testIsSupportedType() { + Class[] unsupportedClasses = + new Class[] {ClassIsAnnotation.class, ClassIsEnum.class, ClassIsFinal.class, + ClassIsInterface.class}; + Class[] supportedClasses = new Class[] {Object.class}; + + for (Class clazz : unsupportedClasses) { + assertFalse(getAndroidMockGenerator().classIsSupportedType(clazz)); + } + for (Class clazz : supportedClasses) { + assertTrue(getAndroidMockGenerator().classIsSupportedType(clazz)); + } + } + + public void testGetDelegateFieldName() { + assertEquals("delegateMockObject", getAndroidMockGenerator().getDelegateFieldName()); + } + + public void testGetInterfaceMethodSource() throws SecurityException, NoSuchMethodException { + Method method = Object.class.getMethod("equals", Object.class); + assertEquals("public boolean equals(java.lang.Object arg0);", getAndroidMockGenerator() + .getInterfaceMethodSource(method)); + } + + public void testGetInterfaceMethodSourceMultipleExceptions() throws SecurityException, + NoSuchMethodException { + Method method = Class.class.getDeclaredMethod("newInstance"); + assertEquals("public java.lang.Object newInstance() throws java.lang.InstantiationException," + + "java.lang.IllegalAccessException;", getAndroidMockGenerator().getInterfaceMethodSource( + method)); + } + + public void testGetInterfaceMethodSourceProtectedMethod() throws SecurityException, + NoSuchMethodException { + Method method = Object.class.getDeclaredMethod("finalize"); + assertEquals("public void finalize() throws java.lang.Throwable;", getAndroidMockGenerator() + .getInterfaceMethodSource(method)); + } + + public void testGetInterfaceMethodSourceNoParams() throws SecurityException, + NoSuchMethodException { + Method method = Object.class.getMethod("toString"); + assertEquals("public java.lang.String toString();", getAndroidMockGenerator() + .getInterfaceMethodSource(method)); + } + + public void testGetInterfaceMethodSourceVoidReturn() throws SecurityException, + NoSuchMethodException { + Method method = Thread.class.getMethod("run"); + assertEquals("public void run();", getAndroidMockGenerator().getInterfaceMethodSource(method)); + } + + public void testGetInterfaceMethodSourceFinal() throws SecurityException, NoSuchMethodException { + Method method = Object.class.getMethod("notify"); + try { + getAndroidMockGenerator().getInterfaceMethodSource(method); + fail("Exception not thrown on a final method"); + } catch (UnsupportedOperationException e) { + // expected + } + } + + public void testGetInterfaceMethodSourceStatic() throws SecurityException, NoSuchMethodException { + Method method = Thread.class.getMethod("currentThread"); + try { + getAndroidMockGenerator().getInterfaceMethodSource(method); + fail("Exception not thrown on a static method"); + } catch (UnsupportedOperationException e) { + // expected + } + } + + public void testGetInterfaceName() { + AndroidMockGenerator r = getAndroidMockGenerator(); + assertEquals("genmocks.java.lang.ObjectDelegateInterface", + FileUtils.getInterfaceNameFor(Object.class, SdkVersion.UNKNOWN)); + } + + public void testGetSubclassName() { + AndroidMockGenerator r = getAndroidMockGenerator(); + assertEquals("genmocks.java.lang.ObjectDelegateSubclass", + FileUtils.getSubclassNameFor(Object.class, SdkVersion.UNKNOWN)); + } + + public void testGetDelegateMethodSource() throws SecurityException, NoSuchMethodException { + Method method = Object.class.getMethod("equals", Object.class); + assertEquals("public boolean equals(java.lang.Object arg0){if(this.delegateMockObject==null){" + + "return false;}return this.delegateMockObject.equals(arg0);}", getAndroidMockGenerator() + .getDelegateMethodSource(method)); + } + + public void testGetDelegateMethodSourceAllTypes() throws SecurityException, + NoSuchMethodException { + String[] returnTypes = + new String[] {"boolean", "byte", "short", "int", "long", "char", "float", "double"}; + String[] castTypes = + new String[] {"false", "(byte)0", "(short)0", "(int)0", "(long)0", "(char)0", "(float)0", + "(double)0"}; + for (int i = 0; i < returnTypes.length; ++i) { + Method method = AllTypes.class.getMethod(returnTypes[i] + "Foo"); + assertEquals("public " + returnTypes[i] + " " + returnTypes[i] + + "Foo(){if(this.delegateMockObject==null){return " + castTypes[i] + + ";}return this.delegateMockObject." + returnTypes[i] + "Foo();}", + getAndroidMockGenerator().getDelegateMethodSource(method)); + } + Method method = AllTypes.class.getMethod("objectFoo"); + assertEquals("public java.lang.Object objectFoo(){if(this.delegateMockObject==null){return " + + "null;}return this.delegateMockObject.objectFoo();}", getAndroidMockGenerator() + .getDelegateMethodSource(method)); + method = AllTypes.class.getMethod("voidFoo"); + assertEquals("public void voidFoo(){if(this.delegateMockObject==null){return ;" + + "}this.delegateMockObject.voidFoo();}", getAndroidMockGenerator() + .getDelegateMethodSource(method)); + } + + private class AllTypes { + @SuppressWarnings("unused") + public void voidFoo() { + } + + @SuppressWarnings("unused") + public boolean booleanFoo() { + return false; + } + + @SuppressWarnings("unused") + public byte byteFoo() { + return 0; + } + + @SuppressWarnings("unused") + public short shortFoo() { + return 0; + } + + @SuppressWarnings("unused") + public int intFoo() { + return 0; + } + + @SuppressWarnings("unused") + public long longFoo() { + return 0; + } + + @SuppressWarnings("unused") + public char charFoo() { + return 0; + } + + @SuppressWarnings("unused") + public float floatFoo() { + return 0; + } + + @SuppressWarnings("unused") + public double doubleFoo() { + return 0; + } + + @SuppressWarnings("unused") + public Object objectFoo() { + return null; + } + } + + public void testGetDelegateMethodSourceMultipleExceptions() throws SecurityException, + NoSuchMethodException { + Method method = Class.class.getDeclaredMethod("newInstance"); + assertEquals( + "public java.lang.Object newInstance() throws java.lang.InstantiationException," + + "java.lang.IllegalAccessException{if(this.delegateMockObject==null){return null;}" + + "return this.delegateMockObject.newInstance();}", getAndroidMockGenerator() + .getDelegateMethodSource(method)); + } + + public void testGetDelegateMethodSourceProtectedMethod() throws SecurityException, + NoSuchMethodException { + Method method = Object.class.getDeclaredMethod("finalize"); + assertEquals("public void finalize() throws java.lang.Throwable{if(this.delegateMockObject==" + + "null){return ;}this.delegateMockObject.finalize();}", getAndroidMockGenerator() + .getDelegateMethodSource(method)); + } + + public void testGetDelegateMethodSourceMultiParams() throws SecurityException, + NoSuchMethodException { + Method method = + String.class.getMethod("getChars", Integer.TYPE, Integer.TYPE, char[].class, Integer.TYPE); + assertEquals( + "public void getChars(int arg0,int arg1,char[] arg2,int arg3){if(this." + + "delegateMockObject==null){return ;}this.delegateMockObject.getChars(arg0,arg1,arg2," + + "arg3);}", getAndroidMockGenerator().getDelegateMethodSource(method)); + } + + public void testGetDelegateMethodSourceNoParams() throws SecurityException, + NoSuchMethodException { + Method method = Object.class.getMethod("toString"); + assertEquals( + "public java.lang.String toString(){if(this.delegateMockObject==null){return null;" + + "}return this.delegateMockObject.toString();}", getAndroidMockGenerator() + .getDelegateMethodSource(method)); + } + + public void testGetDelegateMethodSourceVoidReturn() throws SecurityException, + NoSuchMethodException { + Method method = Thread.class.getMethod("run"); + assertEquals("public void run(){if(this.delegateMockObject==null){return ;}this." + + "delegateMockObject.run();}", getAndroidMockGenerator().getDelegateMethodSource(method)); + } + + public void testGetDelegateMethodSourceFinal() throws SecurityException, NoSuchMethodException { + Method method = Object.class.getMethod("notify"); + try { + getAndroidMockGenerator().getDelegateMethodSource(method); + fail("Exception not thrown on a final method"); + } catch (UnsupportedOperationException e) { + // expected + } + } + + public void testGetDelegateMethodSourceStatic() throws SecurityException, NoSuchMethodException { + Method method = Thread.class.getMethod("currentThread"); + try { + getAndroidMockGenerator().getDelegateMethodSource(method); + fail("Exception not thrown on a static method"); + } catch (UnsupportedOperationException e) { + // expected + } + } + + public void testGenerateEmptySubclass() throws ClassNotFoundException, NotFoundException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = mockGenerator.generateInterface(String.class, SdkVersion.UNKNOWN); + CtClass generatedClass = getAndroidMockGenerator().generateSkeletalClass( + String.class, generatedInterface, SdkVersion.UNKNOWN); + + assertEquals("genmocks.java.lang", generatedClass.getPackageName()); + assertEquals("StringDelegateSubclass", generatedClass.getSimpleName()); + assertEquals("java.lang.String", generatedClass.getSuperclass().getName()); + cleanupGeneratedClasses(generatedInterface, generatedClass); + } + + public void testAddMethods() throws ClassNotFoundException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN); + CtClass generatedClass = + mockGenerator.generateSkeletalClass(Number.class, generatedInterface, SdkVersion.UNKNOWN); + + mockGenerator.addMethods(Number.class, generatedClass); + + List expectedNames = getExpectedNamesForNumberClass(); + List actualNames = getMethodNames(generatedClass.getDeclaredMethods()); + assertUnorderedContentsSame(expectedNames, actualNames); + cleanupGeneratedClasses(generatedInterface, generatedClass); + } + + public void testAddMethodsObjectClass() throws ClassNotFoundException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = mockGenerator.generateInterface(Object.class, SdkVersion.UNKNOWN); + CtClass generatedClass = + mockGenerator.generateSkeletalClass(Object.class, generatedInterface, SdkVersion.UNKNOWN); + + mockGenerator.addMethods(Object.class, generatedClass); + + List expectedNames = getExpectedNamesForObjectClass(); + List actualNames = getMethodNames(generatedClass.getDeclaredMethods()); + assertUnorderedContentsSame(expectedNames, actualNames); + cleanupGeneratedClasses(generatedInterface, generatedClass); + } + + public void testAddMethodsUsesSuperclass() throws ClassNotFoundException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = mockGenerator.generateInterface( + BigInteger.class, SdkVersion.UNKNOWN); + CtClass generatedClass = mockGenerator.generateSkeletalClass( + BigInteger.class, generatedInterface, SdkVersion.UNKNOWN); + + mockGenerator.addMethods(BigInteger.class, generatedClass); + + List expectedNames = getExpectedNamesForBigIntegerClass(); + List actualNames = getMethodNames(generatedClass.getDeclaredMethods()); + assertUnorderedContentsSame(expectedNames, actualNames); + cleanupGeneratedClasses(generatedInterface, generatedClass); + } + + public void testGetAllMethods() throws ClassNotFoundException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = mockGenerator.generateInterface( + BigInteger.class, SdkVersion.UNKNOWN); + CtClass generatedClass = mockGenerator.generateSkeletalClass( + BigInteger.class, generatedInterface, SdkVersion.UNKNOWN); + + Method[] methods = mockGenerator.getAllMethods(BigInteger.class); + + List expectedNames = getExpectedSignaturesForBigIntegerClass(); + List actualNames = getMethodSignatures(methods); + assertUnorderedContentsSame(expectedNames, actualNames); + cleanupGeneratedClasses(generatedInterface, generatedClass); + } + + public void testGenerateInterface() { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN); + + List expectedNames = getExpectedNamesForNumberClass(); + List actualNames = getMethodNames(generatedInterface.getDeclaredMethods()); + assertUnorderedContentsSame(expectedNames, actualNames); + cleanupGeneratedClasses(generatedInterface); + } + + public void testAddInterfaceMethods() { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = AndroidMockGenerator.getClassPool().makeInterface("testInterface"); + + mockGenerator.addInterfaceMethods(Number.class, generatedInterface); + + List expectedNames = getExpectedNamesForNumberClass(); + List actualNames = getMethodNames(generatedInterface.getDeclaredMethods()); + assertUnorderedContentsSame(expectedNames, actualNames); + cleanupGeneratedClasses(generatedInterface); + } + + public void testGenerateSubclass() throws ClassNotFoundException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN); + + CtClass generatedClass = + mockGenerator.generateSubClass(Number.class, generatedInterface, SdkVersion.UNKNOWN); + + List expectedNames = getExpectedNamesForNumberClass(true); + List actualNames = getMethodNames(generatedClass.getDeclaredMethods()); + assertUnorderedContentsSame(expectedNames, actualNames); + cleanupGeneratedClasses(generatedInterface, generatedClass); + } + + public void testCreateMockForClass() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + NoFileAndroidMockGenerator mockGenerator = getNoFileMockGenerator(); + List classes = mockGenerator.createMocksForClass(Object.class); + + List expectedNames = new ArrayList(); + String subclassName = "genmocks.java.lang.ObjectDelegateSubclass"; + String interfaceName = "genmocks.java.lang.ObjectDelegateInterface"; + expectedNames.addAll(Arrays.asList(new String[] {subclassName, + interfaceName})); + List actualNames = getClassNames(classes); + assertUnorderedContentsSame(expectedNames, actualNames); + cleanupGeneratedClasses( + ClassPool.getDefault().get(subclassName), + ClassPool.getDefault().get(interfaceName)); + } + + public void testGetSetDelegateMethodSource() { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + CtClass generatedInterface = mockGenerator.generateInterface(Object.class, SdkVersion.UNKNOWN); + String expectedSource = + "public void setDelegate___AndroidMock(genmocks.java.lang.ObjectDelegateInterface obj) {" + + " this.delegateMockObject = obj;}"; + + assertEquals(expectedSource, mockGenerator.getSetDelegateMethodSource(generatedInterface)); + } + + public void testIsForbiddenMethod() throws SecurityException, NoSuchMethodException { + Method[] forbiddenMethods = + new Method[] {Object.class.getMethod("equals", Object.class), + Object.class.getMethod("toString"), Object.class.getMethod("hashCode")}; + Method[] allowedMethods = new Method[] {BigInteger.class.getMethod("toString", Integer.TYPE)}; + for (Method method : forbiddenMethods) { + assertTrue(getAndroidMockGenerator().isForbiddenMethod(method)); + } + for (Method method : allowedMethods) { + assertFalse(getAndroidMockGenerator().isForbiddenMethod(method)); + } + } + + /** + * Support test class for capturing the names of files that would have been + * saved to a jar file. + * + * @author swoodward@google.com (Stephen Woodward) + */ + class NoFileAndroidMockGenerator extends AndroidMockGenerator { + List savedClasses = new ArrayList(); + + @Override + void saveCtClass(CtClass clazz) { + savedClasses.add(clazz); + } + } +} diff --git a/tests/com/google/android/testing/mocking/AndroidMockTest.java b/tests/com/google/android/testing/mocking/AndroidMockTest.java new file mode 100644 index 0000000..56fcbb3 --- /dev/null +++ b/tests/com/google/android/testing/mocking/AndroidMockTest.java @@ -0,0 +1,927 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.Modifier; +import javassist.NotFoundException; +import javassist.expr.ExprEditor; +import javassist.expr.MethodCall; + +import junit.framework.TestCase; + +import org.easymock.Capture; +import org.easymock.IAnswer; +import org.easymock.LogicalOperator; +import org.easymock.internal.matchers.Equals; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInput; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.SimpleTimeZone; +import java.util.Vector; + + +/** + * Tests for the AndroidMock class. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class AndroidMockTest extends TestCase { + private List notForwardedMethods = + new ArrayList(Arrays.asList(new String[] { + "com.google.android.testing.mocking.AndroidMock.getInterfaceFor(java.lang.Class)", + "com.google.android.testing.mocking.AndroidMock.getSubclassNameFor(java.lang.Class)", + "com.google.android.testing.mocking.AndroidMock.getSubclassFor(java.lang.Class," + + "java.lang.Class,java.lang.Object)", + "com.google.android.testing.mocking.AndroidMock.getInterfaceNameFor(java.lang.Class)", + "com.google.android.testing.mocking.AndroidMock.createStrictMock(" + + "java.lang.Class,java.lang.Object[])", + "com.google.android.testing.mocking.AndroidMock.createStrictMock(" + + "java.lang.String,java.lang.Class,java.lang.Object[])", + "com.google.android.testing.mocking.AndroidMock.createMock(" + + "java.lang.Class,java.lang.Object[])", + "com.google.android.testing.mocking.AndroidMock.createMock(" + + "java.lang.String,java.lang.Class,java.lang.Object[])", + "com.google.android.testing.mocking.AndroidMock.createNiceMock(" + + "java.lang.Class,java.lang.Object[])", + "com.google.android.testing.mocking.AndroidMock.createNiceMock(" + + "java.lang.String,java.lang.Class,java.lang.Object[])"})); + + private CtMethod[] getForwardedMethods() throws NotFoundException { + List methods = + new ArrayList(Arrays.asList(getAndroidMockCtClass().getDeclaredMethods())); + // Get a copy for safe removal of elements during iteration. + for (CtMethod method : Arrays.asList(methods.toArray(new CtMethod[0]))) { + if (notForwardedMethods.contains(method.getLongName()) + || !Modifier.isPublic(method.getModifiers())) { + methods.remove(method); + } + } + return methods.toArray(new CtMethod[0]); + } + + private CtClass getAndroidMockCtClass() throws NotFoundException { + return ClassPool.getDefault().get("com.google.android.testing.mocking.AndroidMock"); + } + + private void compileClasses(List mockClasses) throws NotFoundException { + for (GeneratedClassFile clazz : mockClasses) { + CtClass ctClass; + ctClass = ClassPool.getDefault().get(clazz.getClassName()); + try { + ctClass.toClass(); + } catch (CannotCompileException e) { + // Just ignore -- this will happen for every class used in more than one test. + } + } + } + + public void testIsUnboxableToPrimitiveAllPrimitives() { + assertTrue(AndroidMock.isUnboxableToPrimitive(Integer.TYPE, new Integer(42), true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Long.TYPE, new Long(42L), true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Short.TYPE, new Short((short) 42), true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Byte.TYPE, new Byte((byte) 42), true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Boolean.TYPE, Boolean.TRUE, true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Float.TYPE, new Float(42.0f), true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Double.TYPE, new Double(42.0), true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Character.TYPE, new Character('a'), true)); + + assertTrue(AndroidMock.isUnboxableToPrimitive(Integer.TYPE, 42, true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Long.TYPE, 42L, true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Short.TYPE, (short) 42, true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Byte.TYPE, (byte) 42, true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Boolean.TYPE, true, true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Float.TYPE, 42.0f, true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Double.TYPE, 42.0, true)); + assertTrue(AndroidMock.isUnboxableToPrimitive(Character.TYPE, 'a', true)); + } + + public void testIsUnboxableToPrimitiveIsObject() { + assertFalse(AndroidMock.isUnboxableToPrimitive(Integer.TYPE, new Object(), false)); + } + + public void testIsUnboxableToPrimitiveAllWideningPrimitives() { + Object[] testValues = + new Object[] {new Byte((byte) 42), new Short((short) 42), new Integer(42), new Long(42L), + new Float(42.0f), new Double(42.0), new Character('a'), Boolean.TRUE}; + boolean[] byteExpected = new boolean[] {true, false, false, false, false, false, false, false}; + boolean[] shortExpected = new boolean[] {true, true, false, false, false, false, true, false}; + boolean[] intExpected = new boolean[] {true, true, true, false, false, false, true, false}; + boolean[] longExpected = new boolean[] {true, true, true, true, false, false, true, false}; + boolean[] floatExpected = new boolean[] {true, true, true, false, true, false, true, false}; + boolean[] doubleExpected = new boolean[] {true, true, true, true, true, true, true, false}; + boolean[] charExpected = new boolean[] {true, true, true, false, false, false, true, false}; + boolean[] booleanExpected = + new boolean[] {false, false, false, false, false, false, false, true}; + + for (int i = 0; i < testValues.length; ++i) { + assertEquals("Convert byte from " + testValues[i].getClass(), byteExpected[i], AndroidMock + .isUnboxableToPrimitive(Byte.TYPE, testValues[i], false)); + assertEquals("Convert short from " + testValues[i].getClass(), shortExpected[i], AndroidMock + .isUnboxableToPrimitive(Short.TYPE, testValues[i], false)); + assertEquals("Convert int from " + testValues[i].getClass(), intExpected[i], AndroidMock + .isUnboxableToPrimitive(Integer.TYPE, testValues[i], false)); + assertEquals("Convert long from " + testValues[i].getClass(), longExpected[i], AndroidMock + .isUnboxableToPrimitive(Long.TYPE, testValues[i], false)); + assertEquals("Convert float from " + testValues[i].getClass(), floatExpected[i], AndroidMock + .isUnboxableToPrimitive(Float.TYPE, testValues[i], false)); + assertEquals("Convert double from " + testValues[i].getClass(), doubleExpected[i], + AndroidMock.isUnboxableToPrimitive(Double.TYPE, testValues[i], false)); + assertEquals("Convert char from " + testValues[i].getClass(), charExpected[i], AndroidMock + .isUnboxableToPrimitive(Character.TYPE, testValues[i], false)); + assertEquals("Convert boolean from " + testValues[i].getClass(), booleanExpected[i], + AndroidMock.isUnboxableToPrimitive(Boolean.TYPE, testValues[i], false)); + } + } + + + public void testIsUnboxableToPrimitiveNotPrimitive() { + try { + AndroidMock.isUnboxableToPrimitive(Object.class, Object.class, false); + fail("Exception should have been thrown"); + } catch (IllegalArgumentException e) { + // expected + } + } + + public void testCreateMock() throws ClassNotFoundException, IOException, CannotCompileException, + NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.expect(mockVector.get(0)).andReturn("Hello World"); + AndroidMock.replay(mockVector); + assertEquals("Hello World", mockVector.get(0).toString()); + AndroidMock.verify(mockVector); + } + + public void testCreateMockUsingParameters() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + compileClasses(mockClasses); + SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, 0, "GMT"); + AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42); + AndroidMock.replay(mockTimeZone); + assertEquals(42, mockTimeZone.getRawOffset()); + AndroidMock.verify(mockTimeZone); + } + + public void testCreateMockUsingProtectedConstructors() throws ClassNotFoundException, + IOException, CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Calendar.class); + compileClasses(mockClasses); + Calendar mockCalendar = AndroidMock.createMock(Calendar.class); + AndroidMock.expect(mockCalendar.getGreatestMinimum(1)).andReturn(42); + AndroidMock.replay(mockCalendar); + assertEquals(42, mockCalendar.getGreatestMinimum(1)); + AndroidMock.verify(mockCalendar); + + // Just don't explode + Calendar newMockCalendar = + AndroidMock.createMock(Calendar.class, new SimpleTimeZone(1, "GMT"), Locale.UK); + } + + public void testCreateMockUsingCastableParameters() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + compileClasses(mockClasses); + SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, 'a', "GMT"); + AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42); + AndroidMock.replay(mockTimeZone); + assertEquals(42, mockTimeZone.getRawOffset()); + AndroidMock.verify(mockTimeZone); + } + + public void testCreateMockUsingUnusableParameters() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + compileClasses(mockClasses); + try { + SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, "GMT"); + fail("Excepted an IllegalArgumentException for incorrect number of constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + try { + SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, 0, null); + fail("Excepted an IllegalArgumentException for indeterminate null constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + try { + SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, 0, new Object()); + fail("Excepted an IllegalArgumentException for incorrect constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + public void testCreateMockUsingInterface() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Map.class); + compileClasses(mockClasses); + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get("key")).andReturn("Hello World"); + AndroidMock.replay(mockMap); + assertEquals("Hello World", mockMap.get("key")); + AndroidMock.verify(mockMap); + } + + public void testCreateMockUsingClass() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.expect(mockVector.get(0)).andReturn("Hello World"); + AndroidMock.replay(mockVector); + assertEquals("Hello World", mockVector.get(0).toString()); + AndroidMock.verify(mockVector); + } + + public void testCreateNiceMock() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createNiceMock(Vector.class); + AndroidMock.expect(mockVector.get(0)).andReturn("Hello World"); + AndroidMock.replay(mockVector); + assertEquals("Hello World", mockVector.get(0).toString()); + AndroidMock.verify(mockVector); + } + + public void testCreateNiceMockUsingUnusableParameters() throws ClassNotFoundException, + IOException, CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + compileClasses(mockClasses); + try { + SimpleTimeZone mockTimeZone = AndroidMock.createNiceMock(SimpleTimeZone.class, "GMT"); + fail("Excepted an IllegalArgumentException for incorrect number of constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + try { + SimpleTimeZone mockTimeZone = AndroidMock.createNiceMock(SimpleTimeZone.class, 0, null); + fail("Excepted an IllegalArgumentException for indeterminate null constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + try { + SimpleTimeZone mockTimeZone = + AndroidMock.createNiceMock(SimpleTimeZone.class, 0, new Object()); + fail("Excepted an IllegalArgumentException for incorrect constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + public void testCreateNiceMockUsingParameters() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + + compileClasses(mockClasses); + SimpleTimeZone mockTimeZone = AndroidMock.createNiceMock(SimpleTimeZone.class, 0, "GMT"); + AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42); + AndroidMock.replay(mockTimeZone); + assertEquals(42, mockTimeZone.getRawOffset()); + AndroidMock.verify(mockTimeZone); + } + + public void testCreateNiceMockUsingCastableParameters() throws ClassNotFoundException, + IOException, CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + + compileClasses(mockClasses); + SimpleTimeZone mockTimeZone = AndroidMock.createNiceMock(SimpleTimeZone.class, 'a', "GMT"); + AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42); + AndroidMock.replay(mockTimeZone); + assertEquals(42, mockTimeZone.getRawOffset()); + AndroidMock.verify(mockTimeZone); + } + + public void testCreateNiceMockUsingInterface() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Map.class); + + compileClasses(mockClasses); + Map mockMap = AndroidMock.createNiceMock(Map.class); + AndroidMock.expect(mockMap.get("key")).andReturn("Hello World"); + AndroidMock.replay(mockMap); + assertEquals("Hello World", mockMap.get("key")); + AndroidMock.verify(mockMap); + } + + public void testCreateNiceMockUsingClass() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createNiceMock(Vector.class); + AndroidMock.expect(mockVector.get(0)).andReturn("Hello World"); + AndroidMock.replay(mockVector); + assertEquals("Hello World", mockVector.get(0).toString()); + AndroidMock.verify(mockVector); + } + + public void testCreateStrictMock() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createStrictMock(Vector.class); + AndroidMock.expect(mockVector.get(0)).andReturn("Hello World"); + AndroidMock.replay(mockVector); + assertEquals("Hello World", mockVector.get(0).toString()); + AndroidMock.verify(mockVector); + } + + public void testCreateStrictMockUsingUnusableParameters() throws ClassNotFoundException, + IOException, CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + + compileClasses(mockClasses); + try { + SimpleTimeZone mockTimeZone = AndroidMock.createStrictMock(SimpleTimeZone.class, "GMT"); + fail("Excepted an IllegalArgumentException for incorrect number of constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + try { + SimpleTimeZone mockTimeZone = AndroidMock.createStrictMock(SimpleTimeZone.class, 0, null); + fail("Excepted an IllegalArgumentException for indeterminate null constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + try { + SimpleTimeZone mockTimeZone = + AndroidMock.createStrictMock(SimpleTimeZone.class, 0, new Object()); + fail("Excepted an IllegalArgumentException for incorrect constructor parameters"); + } catch (IllegalArgumentException e) { + // Expected + } + } + + public void testCreateStrictMockUsingParameters() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + + compileClasses(mockClasses); + SimpleTimeZone mockTimeZone = AndroidMock.createStrictMock(SimpleTimeZone.class, 0, "GMT"); + AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42); + AndroidMock.replay(mockTimeZone); + assertEquals(42, mockTimeZone.getRawOffset()); + AndroidMock.verify(mockTimeZone); + } + + public void testCreateStrictMockUsingCastableParameters() throws ClassNotFoundException, + IOException, CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class); + + compileClasses(mockClasses); + SimpleTimeZone mockTimeZone = AndroidMock.createStrictMock(SimpleTimeZone.class, 'a', "GMT"); + AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42); + AndroidMock.replay(mockTimeZone); + assertEquals(42, mockTimeZone.getRawOffset()); + AndroidMock.verify(mockTimeZone); + } + + public void testCreateStrictMockUsingInterface() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Map.class); + + compileClasses(mockClasses); + Map mockMap = AndroidMock.createStrictMock(Map.class); + AndroidMock.expect(mockMap.get("key")).andReturn("Hello World"); + AndroidMock.replay(mockMap); + assertEquals("Hello World", mockMap.get("key")); + AndroidMock.verify(mockMap); + } + + public void testCreateStrictMockUsingClass() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createStrictMock(Vector.class); + AndroidMock.expect(mockVector.get(0)).andReturn("Hello World"); + AndroidMock.replay(mockVector); + assertEquals("Hello World", mockVector.get(0).toString()); + AndroidMock.verify(mockVector); + } + + public void testCreateMockConstructorDoesWorkOnAllReturnTypes() throws ClassNotFoundException, + IOException, CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(ClassDoesWorkInConstructor.class); + compileClasses(mockClasses); + ClassDoesWorkInConstructor mock = AndroidMock.createMock(ClassDoesWorkInConstructor.class); + } + + public void testAllForwardedMethods() throws CannotCompileException, NotFoundException { + for (CtMethod method : getForwardedMethods()) { + MethodVerifier verifier = new MethodVerifier(method); + // CtMethod.instrument Causes every instruction in the method to be + // inspected, and passed to + // the MethodVerifier callback (extends javassist.expr.ExprEditor). We + // want to verify that + // the expected EasyMock method is called at least once in each + // AndroidMock method. + method.instrument(verifier); + assertTrue(method.getLongName() + " not called.", verifier.expectedMethodCalled()); + } + } + + public void testCheckOrder() throws ClassNotFoundException, IOException, CannotCompileException, + NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.checkOrder(mockVector, false); + AndroidMock.checkOrder(AndroidMock.createMock(Map.class), false); + } + + public void testVerify() throws ClassNotFoundException, IOException, CannotCompileException, + NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.replay(mockVector); + AndroidMock.verify(mockVector); + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.replay(mockMap); + AndroidMock.verify(mockMap); + } + + public void testResetToStrict() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.resetToStrict(mockVector); + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.resetToStrict(mockMap); + } + + public void testResetToDefault() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.resetToDefault(mockVector); + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.resetToDefault(mockMap); + } + + public void testResetToNice() throws ClassNotFoundException, IOException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.resetToNice(mockVector); + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.resetToNice(mockMap); + } + + public void testReset() throws ClassNotFoundException, IOException, CannotCompileException, + NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.reset(mockVector); + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.reset(mockMap); + + } + + public void testReplay() throws ClassNotFoundException, IOException, CannotCompileException, + NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(Vector.class); + compileClasses(mockClasses); + Vector mockVector = AndroidMock.createMock(Vector.class); + AndroidMock.replay(mockVector); + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.replay(mockMap); + } + + public void testExpect() { + Map mockMap = AndroidMock.createMock(Map.class); + mockMap.clear(); + AndroidMock.expect(null); + AndroidMock.replay(mockMap); + } + + public void testExpectLastCall() { + Map mockMap = AndroidMock.createMock(Map.class); + mockMap.clear(); + AndroidMock.expectLastCall(); + AndroidMock.replay(mockMap); + } + + public void testAnyBoolean() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyBoolean())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnyByte() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyByte())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnyChar() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyChar())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnyInt() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyInt())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnyLong() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyLong())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnyFloat() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyFloat())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnyDouble() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyDouble())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnyShort() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyShort())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnyObject() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.anyObject())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testGeq() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.geq((byte) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.geq((short) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.geq(0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.geq(0L))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.geq(0.0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.geq(0.0f))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.geq("Hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testLeq() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.leq((byte) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.leq((short) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.leq(0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.leq(0L))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.leq(0.0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.leq(0.0f))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.leq("Hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testGt() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.gt((byte) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.gt((short) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.gt(0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.gt(0L))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.gt(0.0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.gt(0.0f))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.gt("Hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testLt() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.lt((byte) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.lt((short) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.lt(0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.lt(0L))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.lt(0.0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.lt(0.0f))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.lt("Hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testIsA() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.isA(String.class))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testContains() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.contains("hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAnd() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(true), AndroidMock.eq(true)))) + .andReturn(null); + AndroidMock.expect( + mockMap.get(AndroidMock.and(AndroidMock.eq((byte) 0), AndroidMock.eq((byte) 0)))) + .andReturn(null); + AndroidMock.expect( + mockMap.get(AndroidMock.and(AndroidMock.eq((short) 0), AndroidMock.eq((short) 0)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(0), AndroidMock.eq(0)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(0L), AndroidMock.eq(0L)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(0.0), AndroidMock.eq(0.0)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(0.0f), AndroidMock.eq(0.0f)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq("hi"), AndroidMock.eq("hi")))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq('a'), AndroidMock.eq('a')))) + .andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testOr() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(true), AndroidMock.eq(true)))) + .andReturn(null); + AndroidMock.expect( + mockMap.get(AndroidMock.or(AndroidMock.eq((byte) 0), AndroidMock.eq((byte) 0)))) + .andReturn(null); + AndroidMock.expect( + mockMap.get(AndroidMock.or(AndroidMock.eq((short) 0), AndroidMock.eq((short) 0)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(0), AndroidMock.eq(0)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(0L), AndroidMock.eq(0L)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(0.0), AndroidMock.eq(0.0)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(0.0f), AndroidMock.eq(0.0f)))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq("hi"), AndroidMock.eq("hi")))) + .andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq('a'), AndroidMock.eq('a')))) + .andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testNot() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(true)))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq((byte) 0)))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq((short) 0)))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(0)))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(0L)))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(0.0)))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(0.0f)))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq("hi")))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq('a')))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testEq() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.eq(true))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq((byte) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq((short) 0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq(0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq(0L))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq(0.0))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq(0.0f))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq(0.0, 0.1))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq(0.0f, 0.1f))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq("hi"))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.eq('a'))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testAryEq() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new boolean[] {true}))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new byte[] {(byte) 0}))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new short[] {(short) 0}))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new int[] {0}))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new long[] {0L}))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new double[] {0.0}))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new float[] {0.0f}))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new String[] {"hi"}))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new char[] {'a'}))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testIsNull() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.isNull())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testNotNull() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.notNull())).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testFind() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.find("hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testMatches() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.matches("hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testStartsWith() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.startsWith("hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testEndsWith() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.endsWith("hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testSame() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.same("hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testCmpEq() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.cmpEq("hi"))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testCmp() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect( + mockMap.get(AndroidMock.cmp("hi", String.CASE_INSENSITIVE_ORDER, LogicalOperator.EQUAL))) + .andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testCapture() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture()))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture()))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture()))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture()))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture()))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture()))).andReturn(null); + AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture()))).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testReportMatcher() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.reportMatcher(new Equals(null)); + AndroidMock.expect(mockMap.get(null)).andReturn(null); + AndroidMock.replay(mockMap); + } + + public void testGetCurrentArguments() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.expect(mockMap.get(null)).andAnswer(new IAnswer() { + @Override + public Object answer() { + AndroidMock.getCurrentArguments(); + return null; + } + }); + AndroidMock.replay(mockMap); + mockMap.get(null); + } + + public void testMakeThreadSafe() { + Map mockMap = AndroidMock.createMock(Map.class); + AndroidMock.makeThreadSafe(mockMap, false); + AndroidMock.replay(mockMap); + } + + public void testAndThrowsOnMockedInterface() throws IOException { + ObjectInput mockInStream = AndroidMock.createMock(ObjectInput.class); + AndroidMock.expect(mockInStream.read()).andThrow(new IOException("foo")); + AndroidMock.replay(mockInStream); + try { + mockInStream.read(); + fail("IOException not thrown"); + } catch (IOException e) { + assertEquals("foo", e.getMessage()); + } + AndroidMock.verify(mockInStream); + } + + public void testAndThrowsOnMockedClass() throws IOException, ClassNotFoundException, + CannotCompileException, NotFoundException { + List mockClasses = + new AndroidMockGenerator().createMocksForClass(InputStream.class); + compileClasses(mockClasses); + InputStream mockInStream = AndroidMock.createMock(InputStream.class); + AndroidMock.expect(mockInStream.read()).andThrow(new IOException("foo")); + AndroidMock.replay(mockInStream); + try { + mockInStream.read(); + fail("IOException not thrown"); + } catch (IOException e) { + assertEquals("foo", e.getMessage()); + } + AndroidMock.verify(mockInStream); + } + + /** + * Used for testing that a given method on Android Mock calls the equivalent + * method on EasyMock, to ensure that the method-wiring of Android Mock is + * correct. + * + * @author swoodward@google.com (Stephen Woodward) + */ + class MethodVerifier extends ExprEditor { + private CtMethod expectedMethod; + private boolean methodCalled; + + MethodVerifier(CtMethod expectedMethod) { + this.expectedMethod = expectedMethod; + } + + @Override + public void edit(MethodCall calledMethod) { + try { + methodCalled = methodCalled || expectedMethod.equals(calledMethod.getMethod()); + } catch (NotFoundException e) { + throw new RuntimeException(e); + } + } + + public boolean expectedMethodCalled() { + return methodCalled; + } + } +} diff --git a/tests/com/google/android/testing/mocking/ClassDoesWorkInConstructor.java b/tests/com/google/android/testing/mocking/ClassDoesWorkInConstructor.java new file mode 100644 index 0000000..a8c6a55 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassDoesWorkInConstructor.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + + +/** + * Support class for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ClassDoesWorkInConstructor { + public ClassDoesWorkInConstructor() { + this.fooInt(1); + this.fooByte((byte) 1); + this.fooShort((short) 1); + this.fooChar('a'); + this.fooLong(1L); + this.fooFloat(1.0f); + this.fooDouble(1.0); + this.fooBoolean(true); + this.fooObject("hello"); + this.fooVoid(); + } + + public void fooVoid() { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public Object fooObject(String string) { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public boolean fooBoolean(boolean b) { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public double fooDouble(double d) { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public float fooFloat(float f) { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public long fooLong(long i) { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public char fooChar(char c) { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public short fooShort(short s) { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public byte fooByte(byte b) { + throw new IllegalStateException("I wasn't mocked!!"); + } + + public int fooInt(int i) { + throw new IllegalStateException("I wasn't mocked!!"); + } +} diff --git a/tests/com/google/android/testing/mocking/ClassHasDelegateMethods.java b/tests/com/google/android/testing/mocking/ClassHasDelegateMethods.java new file mode 100644 index 0000000..6745b91 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassHasDelegateMethods.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Class with methods that match the delegate methods. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ClassHasDelegateMethods { + /** + * Test method. + * @param obj test obj. + */ + public void setDelegate___AndroidMock(Object obj) { + } + + /** + * Test method + * @return null + */ + public Object getDelegate___AndroidMock() { + return null; + } +} diff --git a/tests/com/google/android/testing/mocking/ClassHasFinalMethods.java b/tests/com/google/android/testing/mocking/ClassHasFinalMethods.java new file mode 100644 index 0000000..414f5f8 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassHasFinalMethods.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Class with final methods. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ClassHasFinalMethods { + public final int foo() { + return 0; + } + + public int bar() { + return 0; + } + + public final int foobar() { + return 0; + } +} diff --git a/tests/com/google/android/testing/mocking/ClassHasNoDefaultConstructor.java b/tests/com/google/android/testing/mocking/ClassHasNoDefaultConstructor.java new file mode 100644 index 0000000..8b97cd8 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassHasNoDefaultConstructor.java @@ -0,0 +1,31 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Class with no default constructor. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ClassHasNoDefaultConstructor { + public ClassHasNoDefaultConstructor(int foo) { + + } + + public int foo() { + return 0; + } +} diff --git a/tests/com/google/android/testing/mocking/ClassHasNoPublicConstructors.java b/tests/com/google/android/testing/mocking/ClassHasNoPublicConstructors.java new file mode 100644 index 0000000..20533ee --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassHasNoPublicConstructors.java @@ -0,0 +1,27 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Class with no public constructor. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ClassHasNoPublicConstructors { + private ClassHasNoPublicConstructors() { + + } +} diff --git a/tests/com/google/android/testing/mocking/ClassHasOverloadedMethods.java b/tests/com/google/android/testing/mocking/ClassHasOverloadedMethods.java new file mode 100644 index 0000000..f1b04fa --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassHasOverloadedMethods.java @@ -0,0 +1,30 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Class with overloaded methods. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ClassHasOverloadedMethods { + public int foo() { + return 0; + } + + public void foo(int arg) { + } +} diff --git a/tests/com/google/android/testing/mocking/ClassHasStaticMethods.java b/tests/com/google/android/testing/mocking/ClassHasStaticMethods.java new file mode 100644 index 0000000..29f4f52 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassHasStaticMethods.java @@ -0,0 +1,31 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Class with static methods. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ClassHasStaticMethods { + public static int staticFoo() { + return 0; + } + + public int foo() { + return 1; + } +} diff --git a/tests/com/google/android/testing/mocking/ClassIsAnnotation.java b/tests/com/google/android/testing/mocking/ClassIsAnnotation.java new file mode 100644 index 0000000..e42c8e1 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassIsAnnotation.java @@ -0,0 +1,25 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Annotation Class. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public @interface ClassIsAnnotation { + +} diff --git a/tests/com/google/android/testing/mocking/ClassIsEnum.java b/tests/com/google/android/testing/mocking/ClassIsEnum.java new file mode 100644 index 0000000..b7fa957 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassIsEnum.java @@ -0,0 +1,25 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Enum Class. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public enum ClassIsEnum { + One, Two, Three, Four; +} diff --git a/tests/com/google/android/testing/mocking/ClassIsFinal.java b/tests/com/google/android/testing/mocking/ClassIsFinal.java new file mode 100644 index 0000000..88f8279 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassIsFinal.java @@ -0,0 +1,27 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Final Class. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public final class ClassIsFinal { + public int foo() { + return 0; + } +} diff --git a/tests/com/google/android/testing/mocking/ClassIsInterface.java b/tests/com/google/android/testing/mocking/ClassIsInterface.java new file mode 100644 index 0000000..d48f512 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassIsInterface.java @@ -0,0 +1,25 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +/** + * Interface. Used only for testing. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public interface ClassIsInterface { + int foo(); +} diff --git a/tests/com/google/android/testing/mocking/ClassTypeTests.java b/tests/com/google/android/testing/mocking/ClassTypeTests.java new file mode 100644 index 0000000..a4d60c2 --- /dev/null +++ b/tests/com/google/android/testing/mocking/ClassTypeTests.java @@ -0,0 +1,269 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.NotFoundException; + +import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * Various tests that verify that different types of Classes are handled + * correctly. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ClassTypeTests extends TestCase { + private AndroidMockGenerator androidMockGenerator = new AndroidMockGenerator(); + + private AndroidMockGenerator getAndroidMockGenerator() { + return androidMockGenerator; + } + + private void assertAllMethodNames(List expectedNames, + Map> expectedMethods, List classes) + throws IOException { + for (GeneratedClassFile clazz : classes) { + assertTrue(expectedNames.contains(clazz.getClassName())); + assertUnorderedContentsSame(expectedMethods.get(clazz.getClassName()), getMethodNames(clazz)); + } + } + + private void assertUnorderedContentsSame(Iterable expected, Iterable actual) { + List missingItems = new ArrayList(); + List extraItems = new ArrayList(); + for (T item : expected) { + missingItems.add(item); + } + for (T item : actual) { + missingItems.remove(item); + extraItems.add(item); + } + for (T item : expected) { + extraItems.remove(item); + } + if (missingItems.size() + extraItems.size() != 0) { + String errorMessage = + "Contents were different. Missing: " + Arrays.toString(missingItems.toArray()) + + " Extra: " + Arrays.toString(extraItems.toArray()); + fail(errorMessage); + } + } + + private List getExpectedNames(Class clazz) { + return new ArrayList(Arrays.asList(new String[] { + "genmocks." + clazz.getCanonicalName() + "DelegateInterface", + "genmocks." + clazz.getCanonicalName() + "DelegateSubclass"})); + } + + private Iterable getMethodNames(GeneratedClassFile clazz) throws IOException { + ByteArrayInputStream classInputStream = new ByteArrayInputStream(clazz.getContents()); + CtClass ctClass; + try { + ctClass = ClassPool.getDefault().getCtClass(clazz.getClassName()); + if (ctClass.isFrozen()) { + ctClass.defrost(); + } + } catch (NotFoundException e) { + // That's ok, we're just defrosting any classes that affect us that were created + // by other tests. NotFoundException implies the class is not frozen. + } + ctClass = ClassPool.getDefault().makeClass(classInputStream); + return getMethodNames(ctClass.getDeclaredMethods()); + } + + private List getMethodNames(CtMethod[] methods) { + List methodNames = new ArrayList(); + for (CtMethod method : methods) { + methodNames.add(method.getName()); + } + return methodNames; + } + + private List getMethodNames(Method[] methods, String[] exclusions) { + List methodNames = new ArrayList(); + for (Method method : methods) { + if (!Arrays.asList(exclusions).contains(method.getName())) { + methodNames.add(method.getName()); + } + } + return methodNames; + } + + private Map> getExpectedMethodsMap(List expectedNames, + Class clazz) { + return getExpectedMethodsMap(expectedNames, clazz, new String[0]); + } + + private Map> getExpectedMethodsMap(List expectedNames, + Class clazz, String[] exclusions) { + Map> expectedMethods = new HashMap>(); + expectedMethods.put(expectedNames.get(0), new ArrayList(Arrays.asList(new String[] { + "finalize", "clone"}))); + expectedMethods.put(expectedNames.get(1), new ArrayList(Arrays.asList(new String[] { + "finalize", "clone", "setDelegate___AndroidMock", "getDelegate___AndroidMock"}))); + expectedMethods.get(expectedNames.get(0)).addAll( + getMethodNames(clazz.getDeclaredMethods(), exclusions)); + expectedMethods.get(expectedNames.get(1)).addAll( + getMethodNames(clazz.getDeclaredMethods(), exclusions)); + return expectedMethods; + } + + public void testClassIsDuplicate() throws ClassNotFoundException, IOException, + CannotCompileException { + List classList = + getAndroidMockGenerator().createMocksForClass(Object.class); + List secondClassList = + getAndroidMockGenerator().createMocksForClass(Object.class); + assertEquals(classList, secondClassList); + } + + public void testClassHasDelegateMethods() throws ClassNotFoundException, IOException, + CannotCompileException { + List expectedNames = getExpectedNames(ClassHasDelegateMethods.class); + Map> expectedMethods = + getExpectedMethodsMap(expectedNames, ClassHasDelegateMethods.class, + new String[] {"getDelegate___AndroidMock"}); + // This use case doesn't fit our util in any nice way, so just tweak it. + expectedMethods.get( + "genmocks.com.google.android.testing.mocking.ClassHasDelegateMethodsDelegateInterface") + .add("getDelegate___AndroidMock"); + + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = + mockGenerator.createMocksForClass(ClassHasDelegateMethods.class); + assertEquals(2, classes.size()); + assertAllMethodNames(expectedNames, expectedMethods, classes); + } + + public void testClassHasFinalMethods() throws ClassNotFoundException, IOException, + CannotCompileException { + List expectedNames = getExpectedNames(ClassHasFinalMethods.class); + Map> expectedMethods = + getExpectedMethodsMap(expectedNames, ClassHasFinalMethods.class, new String[] {"foo", + "foobar"}); + + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = + mockGenerator.createMocksForClass(ClassHasFinalMethods.class); + assertEquals(2, classes.size()); + assertAllMethodNames(expectedNames, expectedMethods, classes); + } + + public void testClassHasNoDefaultConstructor() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = + mockGenerator.createMocksForClass(ClassHasNoDefaultConstructor.class); + assertEquals(2, classes.size()); + } + + public void testClassHasNoPublicConstructors() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = + mockGenerator.createMocksForClass(ClassHasNoPublicConstructors.class); + assertEquals(0, classes.size()); + } + + public void testClassHasOverloadedMethods() throws ClassNotFoundException, IOException, + CannotCompileException { + List expectedNames = getExpectedNames(ClassHasOverloadedMethods.class); + Map> expectedMethods = + getExpectedMethodsMap(expectedNames, ClassHasOverloadedMethods.class); + + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = + mockGenerator.createMocksForClass(ClassHasOverloadedMethods.class); + assertEquals(2, classes.size()); + assertAllMethodNames(expectedNames, expectedMethods, classes); + } + + public void testClassHasStaticMethods() throws ClassNotFoundException, IOException, + CannotCompileException { + List expectedNames = getExpectedNames(ClassHasStaticMethods.class); + Map> expectedMethods = + getExpectedMethodsMap(expectedNames, ClassHasStaticMethods.class, + new String[] {"staticFoo"}); + + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = + mockGenerator.createMocksForClass(ClassHasStaticMethods.class); + assertEquals(2, classes.size()); + assertAllMethodNames(expectedNames, expectedMethods, classes); + } + + public void testClassIsAnnotation() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = mockGenerator.createMocksForClass(ClassIsAnnotation.class); + assertEquals(0, classes.size()); + } + + public void testClassIsEnum() throws ClassNotFoundException, IOException, CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = mockGenerator.createMocksForClass(ClassIsEnum.class); + assertEquals(0, classes.size()); + } + + public void testClassIsFinal() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = mockGenerator.createMocksForClass(ClassIsFinal.class); + assertEquals(0, classes.size()); + } + + public void testClassIsInterface() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = mockGenerator.createMocksForClass(ClassIsInterface.class); + assertEquals(0, classes.size()); + } + + public void testClassIsArray() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = mockGenerator.createMocksForClass(Object[].class); + assertEquals(0, classes.size()); + } + + public void testClassIsNormal() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = mockGenerator.createMocksForClass(Object.class); + assertEquals(2, classes.size()); + } + + public void testClassIsPrimitive() throws ClassNotFoundException, IOException, + CannotCompileException { + AndroidMockGenerator mockGenerator = getAndroidMockGenerator(); + List classes = mockGenerator.createMocksForClass(Integer.TYPE); + assertEquals(0, classes.size()); + } +} diff --git a/tests/com/google/android/testing/mocking/ConstructorCreationTests.java b/tests/com/google/android/testing/mocking/ConstructorCreationTests.java new file mode 100644 index 0000000..152918d --- /dev/null +++ b/tests/com/google/android/testing/mocking/ConstructorCreationTests.java @@ -0,0 +1,131 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +import junit.framework.TestCase; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Type; + + +/** + * Tests for mocked objects with non default constructors. + * + * @author swoodward@google.com (Stephen Woodward) + */ +public class ConstructorCreationTests extends TestCase { + public static class Foo { + private int value; + Foo(int value) { this.value = value; } + int get() { return value; } + } + + public static class Bar { + private double value; + Bar(double value) { this.value = value; } + double get() { return value; } + } + + public static class TestClass { + public int v1; + public double v2; + public boolean usedFloatConstructor; + + public TestClass(Foo foo) { + this(foo.get()); + } + + public TestClass(Foo foo, Bar bar) { + this(foo.get(), bar.get()); + } + + public TestClass(int v1) { + this(v1, 0); + } + + public TestClass(int v1, float v2) { + this.v1 = v1; + this.v2 = v2; + usedFloatConstructor = true; + } + + public TestClass(int v1, double v2) { + this.v1 = v1; + this.v2 = (int) v2; + usedFloatConstructor = false; + } + } + + private void hasConstructor(Object... args) { + Constructor constructor = + AndroidMock.getConstructorFor(TestClass.class, args); + assertNotNull(constructor); + } + + private void doesNotHaveConstructor(Object... args) { + try { + Constructor constructor = + AndroidMock.getConstructorFor(TestClass.class, args); + fail("A constructor was found: " + constructor); + } catch (IllegalArgumentException e) { + // expected + } + } + + public void testConstructors() { + hasConstructor(new Foo(1)); + doesNotHaveConstructor(new Bar(2)); + hasConstructor(new Foo(1), new Bar(2)); + hasConstructor(1); + hasConstructor(1, 2); + doesNotHaveConstructor(new Foo(1), 2); + hasConstructor(1, new Integer("2")); + hasConstructor(1, 2.0); + hasConstructor(1, 2.0f); + } + + private void checkConstructor(Object[] args, Type[] expectedTypes) { + Constructor constructor = + AndroidMock.getConstructorFor(TestClass.class, args); + assertNotNull(constructor); + Type[] types = constructor.getGenericParameterTypes(); + assertEquals(expectedTypes.length, types.length); + for (int i = 0; i < expectedTypes.length; ++i) { + assertEquals(expectedTypes[i], types[i]); + } + } + + public void testCorrectConstructor() { + checkConstructor( + new Object[]{new Foo(1)}, + new Type[]{Foo.class}); + checkConstructor( + new Object[]{new Foo(1), new Bar(2)}, + new Type[]{Foo.class, Bar.class}); + checkConstructor( + new Object[]{1}, + new Type[]{Integer.TYPE}); + checkConstructor( + new Object[]{1, new Float("2")}, + new Type[]{Integer.TYPE, Float.TYPE}); + checkConstructor( + new Object[]{1, 2.0}, + new Type[]{Integer.TYPE, Double.TYPE}); + checkConstructor( + new Object[]{1, 2.0f}, + new Type[]{Integer.TYPE, Float.TYPE}); + } +} \ No newline at end of file diff --git a/tests/com/google/android/testing/mocking/FileUtilsTest.java b/tests/com/google/android/testing/mocking/FileUtilsTest.java new file mode 100644 index 0000000..b1058e3 --- /dev/null +++ b/tests/com/google/android/testing/mocking/FileUtilsTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +import junit.framework.TestCase; + +import java.util.Vector; + +/** + * @author swoodward@google.com (Stephen Woodward) + */ +public class FileUtilsTest extends TestCase { + public void testGetFilenameForClass() { + assertEquals("java/lang/Object.class", FileUtils.getFilenameFor(Object.class.getName())); + assertEquals("com/google/android/testing/mocking/FileUtilsTest$InnerClass.class", + FileUtils.getFilenameFor(InnerClass.class.getName())); + } + + public void testGetClassNameFor() { + assertEquals("java/lang/Object.class", FileUtils.getFilenameFor(Object.class.getName())); + assertEquals("com/google/android/testing/mocking/FileUtilsTest$InnerClass.class", + FileUtils.getFilenameFor(InnerClass.class.getName())); + } + + public void testGetInterfaceNameFor() { + assertEquals("v15.genmocks.java.util.VectorDelegateInterface", + FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.CUPCAKE)); + assertEquals("v16.genmocks.java.util.VectorDelegateInterface", + FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.DONUT)); + assertEquals("v201.genmocks.java.util.VectorDelegateInterface", + FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.ECLAIR_0_1)); + assertEquals("v21.genmocks.java.util.VectorDelegateInterface", + FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.ECLAIR_MR1)); + assertEquals("v22.genmocks.java.util.VectorDelegateInterface", + FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.FROYO)); + assertEquals("genmocks.java.util.VectorDelegateInterface", + FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.UNKNOWN)); + } + + public void testGetSubclassNameFor() { + assertEquals("v15.genmocks.java.util.VectorDelegateSubclass", + FileUtils.getSubclassNameFor(Vector.class, SdkVersion.CUPCAKE)); + assertEquals("v16.genmocks.java.util.VectorDelegateSubclass", + FileUtils.getSubclassNameFor(Vector.class, SdkVersion.DONUT)); + assertEquals("v201.genmocks.java.util.VectorDelegateSubclass", + FileUtils.getSubclassNameFor(Vector.class, SdkVersion.ECLAIR_0_1)); + assertEquals("v21.genmocks.java.util.VectorDelegateSubclass", + FileUtils.getSubclassNameFor(Vector.class, SdkVersion.ECLAIR_MR1)); + assertEquals("v22.genmocks.java.util.VectorDelegateSubclass", + FileUtils.getSubclassNameFor(Vector.class, SdkVersion.FROYO)); + assertEquals("genmocks.java.util.VectorDelegateSubclass", + FileUtils.getSubclassNameFor(Vector.class, SdkVersion.UNKNOWN)); + } + + class InnerClass { + } +} diff --git a/tests/com/google/android/testing/mocking/SdkVersionTest.java b/tests/com/google/android/testing/mocking/SdkVersionTest.java new file mode 100644 index 0000000..eb7c764 --- /dev/null +++ b/tests/com/google/android/testing/mocking/SdkVersionTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +import junit.framework.TestCase; + +import java.util.Arrays; +import java.util.List; + +/** + * @author swoodward@google.com (Stephen Woodward) + */ +public class SdkVersionTest extends TestCase { + + public void testGetAllVersions() { + List versions = Arrays.asList(SdkVersion.getAllVersions()); + List values = Arrays.asList(SdkVersion.values()); + assertEquals(5, versions.size()); + assertTrue(values.containsAll(versions)); + assertFalse(versions.contains(SdkVersion.UNKNOWN)); + } + + public void testGetVersionName() { + assertEquals("v15", SdkVersion.CUPCAKE.getVersionName()); + assertEquals("v16", SdkVersion.DONUT.getVersionName()); + assertEquals("v201", SdkVersion.ECLAIR_0_1.getVersionName()); + assertEquals("v21", SdkVersion.ECLAIR_MR1.getVersionName()); + assertEquals("v22", SdkVersion.FROYO.getVersionName()); + assertEquals("", SdkVersion.UNKNOWN.getVersionName()); + assertEquals("Unknown new SDK has been added, update this test", + 6, SdkVersion.values().length); + } + + public void testGetPackagePrefix() { + assertEquals("v15.", SdkVersion.CUPCAKE.getPackagePrefix()); + assertEquals("v16.", SdkVersion.DONUT.getPackagePrefix()); + assertEquals("v201.", SdkVersion.ECLAIR_0_1.getPackagePrefix()); + assertEquals("v21.", SdkVersion.ECLAIR_MR1.getPackagePrefix()); + assertEquals("v22.", SdkVersion.FROYO.getPackagePrefix()); + assertEquals("", SdkVersion.UNKNOWN.getPackagePrefix()); + assertEquals("Unknown new SDK has been added, update this test", + 6, SdkVersion.values().length); + } + + public void testGetCurrentVersion() { + // Always UNKNOWN on the desktop + assertEquals(SdkVersion.UNKNOWN, SdkVersion.getCurrentVersion()); + } + + public void testGetVersionFor() { + assertEquals(SdkVersion.CUPCAKE, SdkVersion.getVersionFor(3)); + assertEquals(SdkVersion.DONUT, SdkVersion.getVersionFor(4)); + assertEquals(SdkVersion.ECLAIR_0_1, SdkVersion.getVersionFor(6)); + assertEquals(SdkVersion.ECLAIR_MR1, SdkVersion.getVersionFor(7)); + assertEquals(SdkVersion.FROYO, SdkVersion.getVersionFor(8)); + assertEquals(SdkVersion.UNKNOWN, SdkVersion.getVersionFor(-1)); + for (int i = 9; i < 50; ++i) { + assertEquals("Unknown new SDK has been added, update this test", + SdkVersion.UNKNOWN, SdkVersion.getVersionFor(i)); + } + } +} diff --git a/tests/com/google/android/testing/mocking/UsesMocksProcessorTest.java b/tests/com/google/android/testing/mocking/UsesMocksProcessorTest.java new file mode 100644 index 0000000..0b8961b --- /dev/null +++ b/tests/com/google/android/testing/mocking/UsesMocksProcessorTest.java @@ -0,0 +1,275 @@ +/* + * Copyright 2010 Google Inc. + * + * 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 com.google.android.testing.mocking; + +import javassist.CannotCompileException; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVisitor; +import javax.tools.JavaFileObject; + +/** + * @author swoodward@google.com (Stephen Woodward) + */ +public class UsesMocksProcessorTest extends TestCase { + + private Set getAnnotatedElementsSet(Class... classes) { + Set set = new HashSet(); + for (Class clazz : classes) { + set.add(getMockElement(clazz)); + } + return set; + } + + @SuppressWarnings("unchecked") + private Element getMockElement(Class clazz) { + Element mockElement = EasyMock.createNiceMock(Element.class); + EasyMock.expect(mockElement.getAnnotationMirrors()).andReturn(getMockAnnotationMirrors(clazz)) + .anyTimes(); + EasyMock.replay(mockElement); + return mockElement; + } + + @SuppressWarnings("unchecked") + private List getMockAnnotationMirrors(Class clazz) { + List mockMirrorList = new ArrayList(); + AnnotationMirror mockMirror = EasyMock.createNiceMock(AnnotationMirror.class); + EasyMock.expect(mockMirror.getAnnotationType()).andReturn(getMockAnnotationType()).anyTimes(); + EasyMock.expect(mockMirror.getElementValues()).andReturn(getMockElementValuesMap(clazz)) + .anyTimes(); + EasyMock.replay(mockMirror); + mockMirrorList.add(mockMirror); + return mockMirrorList; + } + + @SuppressWarnings("unchecked") + private Map getMockElementValuesMap(Class clazz) { + Map mockValuesMap = new HashMap(); + mockValuesMap.put(getMockExecutableElement(), getMockAnnotationValue(clazz)); + return mockValuesMap; + } + + private AnnotationValue getMockAnnotationValue(Class clazz) { + AnnotationValue mockValue = EasyMock.createMock(AnnotationValue.class); + EasyMock.expect(mockValue.getValue()).andReturn( + Arrays.asList(new String[] {clazz.getName() + ".class"})).anyTimes(); + EasyMock.replay(mockValue); + return mockValue; + } + + private ExecutableElement getMockExecutableElement() { + ExecutableElement mockElement = EasyMock.createNiceMock(ExecutableElement.class); + EasyMock.replay(mockElement); + return mockElement; + } + + private DeclaredType getMockAnnotationType() { + return new DeclaredType() { + @Override + public String toString() { + return UsesMocks.class.getName(); + } + + @Override + public Element asElement() { + return null; + } + + @Override + public TypeMirror getEnclosingType() { + return null; + } + + @Override + public List getTypeArguments() { + return null; + } + + @Override + public R accept(TypeVisitor v, P p) { + return null; + } + + @Override + public TypeKind getKind() { + return null; + } + }; + } + + private UsesMocksProcessor getProcessor() { + return getProcessor(getMockProcessingEnvironment()); + } + + private UsesMocksProcessor getProcessor(ProcessingEnvironment processingEnv) { + UsesMocksProcessor processor = new UsesMocksProcessor(); + processor.init(processingEnv); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + processor.logger = new ProcessorLogger(outputStream, processingEnv); + return processor; + } + + private ProcessingEnvironment getMockProcessingEnvironment(Filer mockFiler) { + ProcessingEnvironment mockEnvironment = EasyMock.createNiceMock(ProcessingEnvironment.class); + EasyMock.expect(mockEnvironment.getMessager()).andReturn(getMockMessager()).anyTimes(); + EasyMock.expect(mockEnvironment.getFiler()).andReturn(mockFiler).anyTimes(); + EasyMock.expect(mockEnvironment.getOptions()).andReturn(getMockOptions()).anyTimes(); + EasyMock.replay(mockEnvironment); + return mockEnvironment; + } + + private Map getMockOptions() { + Map map = new HashMap(); + map.put("bin_dir", "."); + map.put("logfile", "logfile"); + return map; + } + + private ProcessingEnvironment getMockProcessingEnvironment() { + return getMockProcessingEnvironment(getMockFiler()); + } + + private Messager getMockMessager() { + Messager mockMessager = EasyMock.createNiceMock(Messager.class); + EasyMock.replay(mockMessager); + return mockMessager; + } + + private Filer getMockFiler() { + try { + return getMockFiler(getMockFileObject()); + } catch (IOException e) { + // Can't happen + throw new RuntimeException(e); + } + } + + private Filer getMockFiler(JavaFileObject mockFileObject) { + Filer mockFiler = EasyMock.createNiceMock(Filer.class); + try { + EasyMock.expect(mockFiler.createClassFile((CharSequence) EasyMock.anyObject())).andReturn( + mockFileObject).anyTimes(); + } catch (IOException e) { + // Can't happen + throw new RuntimeException(e); + } + EasyMock.replay(mockFiler); + return mockFiler; + } + + private JavaFileObject getMockFileObject() throws IOException { + return getMockFileObject(new ByteArrayOutputStream()); + } + + private JavaFileObject getMockFileObject(OutputStream outStream) throws IOException { + JavaFileObject mockFileObject = EasyMock.createNiceMock(JavaFileObject.class); + EasyMock.expect(mockFileObject.openOutputStream()).andReturn(outStream).anyTimes(); + EasyMock.replay(mockFileObject); + return mockFileObject; + } + + private RoundEnvironment getMockRoundEnvironment(Set elementsWithAnnotation) { + return getMockRoundEnvironment(elementsWithAnnotation, false); + } + + @SuppressWarnings("unchecked") + private RoundEnvironment getMockRoundEnvironment(Set elementsWithAnnotation, + boolean finishedProcessing) { + RoundEnvironment mockEnv = EasyMock.createNiceMock(RoundEnvironment.class); + EasyMock.expect(mockEnv.getElementsAnnotatedWith(UsesMocks.class)).andReturn( + (Set) elementsWithAnnotation).anyTimes(); + EasyMock.expect(mockEnv.processingOver()).andReturn(finishedProcessing).anyTimes(); + EasyMock.replay(mockEnv); + return mockEnv; + } + + public void testGetClassMocks() throws IOException, CannotCompileException { + List> classesToMock = new ArrayList>(); + classesToMock.add(TestCase.class); + List expectedMocks = + new ArrayList(Arrays.asList(new String[] { + "genmocks." + TestCase.class.getName() + "DelegateInterface", + "genmocks." + TestCase.class.getName() + "DelegateSubclass"})); + Set mockedClasses = + getProcessor().getClassMocks(classesToMock, true); + + assertEquals(2, mockedClasses.size()); + for (GeneratedClassFile clazz : mockedClasses) { + assertTrue(expectedMocks.contains(clazz.getClassName())); + expectedMocks.remove(clazz.getClassName()); + } + } + + public void testWriteMocks() throws IOException, CannotCompileException { + List> classesToMock = new ArrayList>(); + classesToMock.add(TestCase.class); + Set mockedClassesSet = + getProcessor().getClassMocks(classesToMock, true); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + getProcessor(getMockProcessingEnvironment(getMockFiler(getMockFileObject(outputStream)))) + .writeMocks(mockedClassesSet); + + String output = new String(outputStream.toByteArray()); + for (GeneratedClassFile mockClass : mockedClassesSet) { + String expected = new String(mockClass.getContents()); + assertTrue(output.contains(expected)); + output = output.replace(expected, ""); + } + assertEquals(0, output.length()); + } + + public void testProcess() { + assertFalse(getProcessor().process(null, + getMockRoundEnvironment(getAnnotatedElementsSet(TestCase.class)))); + assertFalse(getProcessor().process(null, + getMockRoundEnvironment(getAnnotatedElementsSet(TestCase.class), true))); + } + + public void testFindClassesToMock() { + Set annotatedElements = getAnnotatedElementsSet(Set.class, TestCase.class); + List> classesList = getProcessor().findClassesToMock(annotatedElements); + + assertEquals(annotatedElements.size(), classesList.size()); + assertTrue(classesList.contains(Set.class)); + assertTrue(classesList.contains(TestCase.class)); + } +} -- cgit v1.2.3