Gavin Miller
Gavin Miller

Reputation: 43815

Android Unit Test throws NoClassDefFoundError on Log

I get a java.lang.NoClassDefFoundError: android/util/Log error when I try to run my unit test project in eclipse.

Distilled down, my test code looks like this:

package com.randomtype.yycparking;

import junit.framework.TestCase;
import android.util.Log;

public class StallTests extends TestCase {  
    public void setUp() {
        Log.v("HI", "Fail");
    }

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

And the code throws an exception on the Log.v call. When I run the android project normally I don't get any exceptions around Log.

Full Stack Trace:

java.lang.NoClassDefFoundError: android/util/Log
    at com.randomtype.yycparking.StallTests.setUp(StallTests.java:11)
    at junit.framework.TestCase.runBare(TestCase.java:132)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:124)
    at junit.framework.TestSuite.runTest(TestSuite.java:243)
    at junit.framework.TestSuite.run(TestSuite.java:238)
    at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassNotFoundException: android.util.Log
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    ... 14 more

As pointed out by dtmilano, I wasn't running the unit tests as an Android JUnit Test. How can you tell the difference? Look for the little a like in the picture below:

Screen shot of a beside JUnit icon
(source: skitch.com)

Upvotes: 8

Views: 7887

Answers (6)

Introspective
Introspective

Reputation: 736

It is year 2023. Eclipse is no longer supported for Android development. I am using the latest & greatest Android Studio (2022.2.1 Patch 2) with Android SDK 33.

JUnit test are in the same module/library as the class to be tested and they are not in a separate module/library. Therefore, using mocks for the Log methods as proposed here, is not practical for me.

Especially when I already had my JUnit tests working without such mocks, before updating my environment from Java 8 to 17, using:

logMockedStatic = Mockito.mockStatic(Log.class);

So... after some troubleshooting, I discovered that the root cause of this newly introduced java.lang.NoClassDefFoundError: android/util/Log (after updating JDK8 to JDK17), was the classpath in my Run/Debug Configurations > JUnit > Build and run section:

I already had -cp MyProj.myLib.main in there, but I needed to add android.jar to eliminate this error. Here is how I did it:

  1. File > Project Structure > SDK Location (find exact path to android.jar)
  2. Run/Debug Configurations > JUnit > Build and run > Modify options: check Modify classpath.
  3. In the newly added box labeled 'Modify classpath' (as a result of last step), click + to add C:\Users\Me\AppData\Local\Android\Sdk\platforms\android-33\android.jar

Works now like a charm.

Upvotes: 1

slhck
slhck

Reputation: 38652

I ran into this issue in the context of running JUnit tests for Android with mocks for the Log methods, since my unit tests should not have relied on Android's own implementation.

So I had mocks in test/java/android/util/Log.java – all except the Log.v method. After adding the v method in the mocks, everything worked again.

package android.util;

public class Log {
    public static int d(String tag, String msg) {
        System.out.println("DEBUG: " + tag + ": " + msg);
        return 0;
    }

    public static int i(String tag, String msg) {
        System.out.println("INFO: " + tag + ": " + msg);
        return 0;
    }

    public static int w(String tag, String msg) {
        System.out.println("WARN: " + tag + ": " + msg);
        return 0;
    }

    public static int e(String tag, String msg) {
        System.out.println("ERROR: " + tag + ": " + msg);
        return 0;
    }

    public static int v(String tag, String msg) {
        System.out.println("VERB: " + tag + ": " + msg);
        return 0;
    }
}

Upvotes: 1

Carl Anderson
Carl Anderson

Reputation: 3476

Today when running the unit tests in my project, I hit this same error - over 100 of my unit tests were suddenly failing, even though they were working a week ago (without me doing any changes). The solution was to restart Android Studio. I think there's a bug in the 3.5.x versions of Android Studio where over time it can lose the configuration for running unit tests and will start throwing errors such as this one.

Upvotes: 2

ahsiu
ahsiu

Reputation: 123

 android {
  // ...
  testOptions { 
    unitTests.returnDefaultValues = true
  }
}

reference http://tools.android.com/tech-docs/unit-testing-support#TOC-Method-...-not-mocked.-

i find my issue: notify your build.gradle file ,you should set the compileSdkVersion equal 23 and the same as targetSdkVersion, it work well.

Upvotes: 1

Mike Argyriou
Mike Argyriou

Reputation: 1310

Same mistake here, other reason...

My test class was in an anonymous package but it was inconistent with AndroidManifest.xml:

<instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="micharg.nameanimalthing" />

[same answer posted here]

Upvotes: 1

Diego Torres Milano
Diego Torres Milano

Reputation: 69189

Your tests should be in a separate Android Test Project (Project -> Android Tools -> New Android Project) and you should run them as Android JUnit Test (Run as -> Android JUnit Test).

Upvotes: 4

Related Questions