1

I try to unit test an activity that extends a SherlockFragmentActivity without success in my application. To isolate the problem I reproduced it in a very simple Sandbox project but I can't figure out how to fix it.

My configuration

I use latest version of Eclipse with SDK & ADT 22.6.2 on Linux Debian.

The project is tested through Emulator, in an Android 2.2 emulated device (API 8).

The target API is Android 4.4.2 (API 19).

JDK 1.6 (I also tried with JDK 1.7, see Could not find class X referenced from method Y).

Problem

I cannot run the unit test on the class that extends SherlockFragmentActivity.

This is the output of the Console tab in Eclipse:

[2014-04-06 13:01:02 - SandboxTest] Dx 
trouble writing output: already prepared 
[2014-04-06 13:01:03 - SandboxTest] ------------------------------
[2014-04-06 13:01:03 - SandboxTest] Android Launch! 
[2014-04-06 13:01:03 - SandboxTest] adb is running normally.
[2014-04-06 13:01:03 - SandboxTest] Performing android.test.InstrumentationTestRunner JUnit launch 
[2014-04-06 13:01:03 - SandboxTest] Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD 'Android_2.2' 
[2014-04-06 13:01:03 - SandboxTest] Uploading SandboxTest.apk onto device 'emulator-5554' [2014-04-06 13:01:03 - SandboxTest] Installing SandboxTest.apk... 
[2014-04-06 13:01:10 - SandboxTest] Success! 
[2014-04-06 13:01:10 - SandboxTest] Project dependency found, installing: Sandbox 
[2014-04-06 13:01:11 - Sandbox] Application already deployed. No need to reinstall. 
[2014-04-06 13:01:11 - SandboxTest] Launching instrumentation android.test.InstrumentationTestRunner on emulator-5554 
[2014-04-06 13:01:15 - SandboxTest] Test run failed: Test run failed to complete. Expected 2 tests, received 0

The Test run failed: Test run failed to complete. Expected 2 tests, received 0 is due to another issue, catched from the LogCat output, which is:

Could not find class 'com.example.sandbox.MainActivity', referenced from method com.example.sandbox.test.MainActivityTest.<init>
Could not find class 'com.example.sandbox.MainActivity', referenced from method com.example.sandbox.test.MainActivityTest.setUp

The full output is here:

Class resolved by unexpected DEX: Lcom/example/sandbox/MainActivity;(0x45fa69a0):0x127410 ref [Lcom/actionbarsherlock/app/SherlockFragmentActivity;] Lcom/actionbarsherlock/app/SherlockFragmentActivity;(0x45fa69a0):0x12f910
(Lcom/example/sandbox/MainActivity; had used a different Lcom/actionbarsherlock/app/SherlockFragmentActivity; during pre-verification)
Unable to resolve superclass of Lcom/example/sandbox/MainActivity; (824)
Link of class 'Lcom/example/sandbox/MainActivity;' failed
Could not find class 'com.example.sandbox.MainActivity', referenced from method com.example.sandbox.test.MainActivityTest.<init>
VFY: unable to resolve const-class 1031 (Lcom/example/sandbox/MainActivity;) in Lcom/example/sandbox/test/MainActivityTest;
Class resolved by unexpected DEX: Lcom/example/sandbox/MainActivity;(0x45fa69a0):0x127410 ref [Lcom/actionbarsherlock/app/SherlockFragmentActivity;] Lcom/actionbarsherlock/app/SherlockFragmentActivity;(0x45fa69a0):0x12f910
(Lcom/example/sandbox/MainActivity; had used a different Lcom/actionbarsherlock/app/SherlockFragmentActivity; during pre-verification)
Unable to resolve superclass of Lcom/example/sandbox/MainActivity; (824)
Link of class 'Lcom/example/sandbox/MainActivity;' failed
Could not find class 'com.example.sandbox.MainActivity', referenced from method com.example.sandbox.test.MainActivityTest.setUp
VFY: unable to resolve const-class 1031 (Lcom/example/sandbox/MainActivity;) in Lcom/example/sandbox/test/MainActivityTest;
Class resolved by unexpected DEX: Lcom/example/sandbox/MainActivity;(0x45fa69a0):0x127410 ref [Lcom/actionbarsherlock/app/SherlockFragmentActivity;] Lcom/actionbarsherlock/app/SherlockFragmentActivity;(0x45fa69a0):0x12f910
(Lcom/example/sandbox/MainActivity; had used a different Lcom/actionbarsherlock/app/SherlockFragmentActivity; during pre-verification)
Unable to resolve superclass of Lcom/example/sandbox/MainActivity; (824)
Link of class 'Lcom/example/sandbox/MainActivity;' failed
Class resolved by unexpected DEX: Lcom/example/sandbox/MainActivity;(0x45fa69a0):0x127410 ref [Lcom/actionbarsherlock/app/SherlockFragmentActivity;] Lcom/actionbarsherlock/app/SherlockFragmentActivity;(0x45fa69a0):0x12f910
(Lcom/example/sandbox/MainActivity; had used a different Lcom/actionbarsherlock/app/SherlockFragmentActivity; during pre-verification)
Unable to resolve superclass of Lcom/example/sandbox/MainActivity; (824)
Link of class 'Lcom/example/sandbox/MainActivity;' failed
Class resolved by unexpected DEX: Lcom/example/sandbox/MainActivity;(0x45fa69a0):0x127410 ref [Lcom/actionbarsherlock/app/SherlockFragmentActivity;] Lcom/actionbarsherlock/app/SherlockFragmentActivity;(0x45fa69a0):0x12f910
(Lcom/example/sandbox/MainActivity; had used a different Lcom/actionbarsherlock/app/SherlockFragmentActivity; during pre-verification)
Unable to resolve superclass of Lcom/example/sandbox/MainActivity; (824)
Link of class 'Lcom/example/sandbox/MainActivity;' failed
VFY: unable to resolve virtual method 8919: Lcom/example/sandbox/MainActivity;.findViewById (I)Landroid/view/View;

What I already tried

I tried solutions from:

Nothing worked.

Sandbox project

First of all I show you the sandbox project and its associated sandbox test project that work for you to reproduce the issue easily.

The sandbox project is very short and easy to understand. There is just a "go" button in a LinearLayout. No action when clicking, nothing complicated.

MainActivity.java

package com.example.sandbox;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="go" />

</LinearLayout>

AndroidManifest.xml

Note here that there is android:theme="@style/Theme.Sherlock" but it's not used yet as the MainActivity extends Activity and not any Sherlock*Activity classes.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.sandbox"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:allowBackup="false"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.Sherlock" >
        <activity
            android:name="com.example.sandbox.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

SandboxTest project

The sandbox test is also very easy to understand, I just check that the text of the button is "go" (we don't care about the test result).

MainActivityTest.java

package com.example.sandbox.test;

import android.content.Intent;
import android.test.ActivityUnitTestCase;
import android.widget.Button;

import com.example.sandbox.MainActivity;
import com.example.sandbox.R;

public class MainActivityTest extends ActivityUnitTestCase<MainActivity> {
    private MainActivity mActivity;

    public MainActivityTest() {
        super(MainActivity.class);
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();

        startActivity(new Intent(getInstrumentation().getTargetContext(), MainActivity.class),
                null, null);

        mActivity = getActivity();
    }

    public void testButton() {

        assertNotNull(mActivity);

        Button b = (Button) mActivity.findViewById(R.id.button);

        assertTrue(b.getText().toString().equalsIgnoreCase("go"));
    }

    public void testDummy() {
        assertTrue(true);
    }

}

What works

With this Sandbox project, when running the test in SandboxTest project it works as expected.

Let's reproduce the issue

To reproduce the issue, it's very easy, just extends the MainActivity of the Sandbox project with SherlockFragmentActivity instead of Activity, like this:

MainActivity.java (2nd version)

package com.example.sandbox;

import android.os.Bundle;

import com.actionbarsherlock.app.SherlockFragmentActivity;

public class MainActivity extends SherlockFragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

When doing this I got the issue previously mentioned at the start of this topic.

I tried to play with the way I import the actionBarSherlock library, but nothing worked.

Libraries configuration in the Eclipse projects

I have checked many QA about the not found class stuff and they all talk about exporting libs and putting jar files in libs/ subdirectory etc. I tried everything and nothing work. I think it's related to actionbarsherlock library.

Nevertheless, let's see my current configuration about libs/ subdirectory:

Sandbox project: I have a libs/ subdirectory with android-support-v4.jar SandboxTest project: no libs/ subdirectory.

Let's see the configuration within Eclipse for each project:

(I cannot add images as I haven't 10 of reputation... :-/)

Sandbox project (right click > properties):

Android:

  • Project Build Target : Android 4.4.2
  • Library : actionbarsherlock

Java Build Path:

  • Projects tab is void
  • Libraries tab contains Android 4.4.2 (android.jar), Android Dependencies (actionbarsherlock.jar), Android Private Libraries (android-support-v4.jar)
  • Order and export tab (in this order): [-]Sandbox/src, [-]Sandbox/gen, [ ] Android 4.4.2, [X] Android Private Libraries, [X] Android Dependencies.

SandboxTest project (right click > properties):

Android:

  • Project Build Target : Android 4.4.2
  • Library : actionbarsherlock (<< This is a mistake remove that in order to work, see the edit section at the end of this post)

Java Build Path:

  • Projects tab contains Sandbox project
  • Libraries tab contains Android 4.4.2 (android.jar), Android Dependencies (actionbarsherlock.jar), Android Private Libraries (android-support-v4.jar)
  • Order and export tab (in this order): [-]SandboxTest/src, [-]SandboxTest/gen, [ ] Sandbox, [ ] Android 4.4.2, [X] Android Private Libraries, [X] Android Dependencies.

I hope someone has an idea. I've lost a half-day on this issue...

Thanks! Jeremy.

EDIT: Solution & workaround

I found the main mistake: the SandboxTest project must NOT have a dependency to actionbarsherlock.

I recommend also to use JDK 1.6.

After removing the dependency, the Could not find class error disappears. It is replaced by this one:

java.lang.IllegalStateException: You must use Theme.Sherlock, Theme.Sherlock.Light, Theme.Sherlock.Light.DarkActionBar, or a derivative.
at com.actionbarsherlock.internal.ActionBarSherlockCompat.generateLayout(ActionBarSherlockCompat.java:976)
at com.actionbarsherlock.internal.ActionBarSherlockCompat.installDecor(ActionBarSherlockCompat.java:902)
at com.actionbarsherlock.internal.ActionBarSherlockCompat.setContentView(ActionBarSherlockCompat.java:836)
at com.actionbarsherlock.app.SherlockFragmentActivity.setContentView(SherlockFragmentActivity.java:261)
at com.example.sandbox.MainActivity.onCreate(MainActivity.java:13)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.test.ActivityUnitTestCase.startActivity(ActivityUnitTestCase.java:159)
at com.example.sandbox.test.MainActivityTest.testText(MainActivityTest.java:18)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:204)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:194)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:520)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)

It's the typical mistake in ActionBarSherlock when you don't use one of the Sherlock Theme in your app. I use Theme.Sherlock in the Sandbox project (as in my real app) but not in my SandboxTest project.

The error message seems to tell me that I must use also the Theme.Sherlock theme in the SandboxTest project. But if I want to do that, I must add back the dependency to actionbarsherlock which would lead again to my first issue.

Workaround

I found a way to run the test correctly by using a ContextThemeWrapper in my SandboxTest project. Thanks to fidanov, see original message here: https://github.com/JakeWharton/ActionBarSherlock/issues/454#issuecomment-10472928.

MainActivityTest (workaround inside)

The new setUp() method is:

@Override
    public void setUp() throws Exception {
        super.setUp();

        ContextThemeWrapper context = new ContextThemeWrapper(getInstrumentation()
            .getTargetContext(), R.style.HerculeTheme);
        setActivityContext(context);

        startActivity(new Intent(context, MainActivity.class),
                null, null);

        mActivity = getActivity();
    }

Now when I run my unit test, it doesn't bother me anymore about using the Theme.Sherlock and it works.

Thanks, Jeremy.

Community
  • 1
  • 1
Jeremy
  • 11
  • 3
  • thanks Jeremy! I was stuck with the IllegalStateException on the theme! finally, my tests run on all devices :-) – matthes May 13 '14 at 12:15

0 Answers0