androidunit-testingmavenm2ejmockit

What is the difference between running JUnit tests with "Run As" and Maven's test?


I have some problems I don't understand exactly. I have some class called ApplicationContext which extends android.app.Application. This class will be mocked by JMockIt's MockUp<T>. When I let my JUnit tests run by mvn install, everything works well, but when I run my tests with Run As->JUnit Test I get exceptions like this (only with this one test which extends android.app.Application)...

java.lang.TypeNotPresentException: Type [unknown] not present

I guess that this has something to do with the fact that android must be in provided scope:

    <dependency>
        <groupId>com.google.android</groupId>
        <artifactId>android</artifactId>
        <version>${platform.version}</version>
        <scope>provided</scope>
    </dependency>

Maybe the tests don't have this package at runtime or something. But I wonder why they just have it at mvn install, since the package is always linked as Maven dependency. I need to understand why classes from android.app.Application are not found when I run test with "Run As". Here are some of my configuration settings:

Build path

.classpath

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
    <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
    <classpathentry kind="src" output="bin/classes" path="src/main/java">
        <attributes>
            <attribute name="optional" value="true"/>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="src" path="gen"/>
    <classpathentry kind="src" output="bin/classes" path="src/test/java">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="output" path="bin/classes"/>
</classpath>

.project

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
    <name>net.devgems.android.kurzparkzonewien-TRUNK</name>
    <comment></comment>
    <projects>
    </projects>
    <buildSpec>
        <buildCommand>
            <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>org.eclipse.jdt.core.javabuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>com.android.ide.eclipse.adt.ApkBuilder</name>
            <arguments>
            </arguments>
        </buildCommand>
        <buildCommand>
            <name>org.eclipse.m2e.core.maven2Builder</name>
            <arguments>
            </arguments>
        </buildCommand>
    </buildSpec>
    <natures>
        <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
        <nature>org.eclipse.jdt.core.javanature</nature>
        <nature>org.eclipse.m2e.core.maven2Nature</nature>
    </natures>
</projectDescription>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.devgems.android</groupId>
    <artifactId>kurzparkzonewien</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>apk</packaging>
    <name>kurzparkzonewien</name>

    <properties>
        <platform.version>1.6_r2</platform.version>
        <android.sdk.path>/opt/android-sdk-linux</android.sdk.path>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.google.android</groupId>
            <artifactId>android</artifactId>
            <version>${platform.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
            <version>1.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.googlecode.jmockit</groupId>
            <artifactId>jmockit</artifactId>
            <version>0.999.17</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.google.android</groupId>
            <artifactId>support-v4</artifactId>
            <version>r6</version>
        </dependency>
    </dependencies>

    <build>
        <outputDirectory>bin/classes</outputDirectory>
        <testOutputDirectory>bin/test-classes</testOutputDirectory>

        <plugins>
            <plugin>
                <groupId>com.jayway.maven.plugins.android.generation2</groupId>
                <artifactId>android-maven-plugin</artifactId>
                <version>3.1.1</version>
                <configuration>
                    <androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>
                    <assetsDirectory>${project.basedir}/assets</assetsDirectory>
                    <resourceDirectory>${project.basedir}/res</resourceDirectory>
                    <nativeLibrariesDirectory>${project.basedir}/src/main/native</nativeLibrariesDirectory>
                    <sdk>
                        <platform>4</platform>
                        <path>${android.sdk.path}</path>
                    </sdk>
                    <undeployBeforeDeploy>true</undeployBeforeDeploy>
                </configuration>
                <extensions>true</extensions>
            </plugin>

            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

If you need more additional information, please tell me, because I'm not sure where to isolate the problem properly.


Solution

  • I came to the conclusion that the error explained in my question is the proper behavior. This is so because you must not expect from an Eclipse project that Eclipse (or the ADT plugin) knows how to deal with dependencies organized by Maven. This is a Maven project, so Maven must be used to install, deploy and test. I think the difference between "Run As" and "mvn test" is, that the first uses the Eclipse's built in JUnit libraries located in plugins directory, the latter uses the libraries configured by Maven. So these are two different worlds and they have nothing in common. In my opinion it's just coincidence that a Maven project mostly works with Eclipse Run As and so on. But if there are dependency issues, Eclipse cannot manage it, since it is a Maven project and not an Eclipse project.

    But for this case above I found a nice workaround which works at least for testing. I have to go to "Java Build Path -> Libraries" and I had to add all Maven dependencies including the used android.jar as external dependency (it doesn't affect Maven). Then I was able to execute all tests by "Run As -> JUnit Test" (whereby sometimes I have to execute "Project Clean" at first, because otherwise I run into ClassNotFoundExceptions).

    If I'm wrong with my assumptions, feel free to correct me.