NoClassDefFoundError when running Android JUnit test

First of all, there are the same questions as here or here , but I don’t have any external libraries or the lib folder, some of the included jars or something else, so I'm wondering what I'm doing wrong by running Android Junit tests.

My project structure is as follows:
enter image description here

As you can see, I have a separate project for Android JUnit tests. The testing class is as follows:

public class PersistenceManager { private static final String FILENAME = "kpzwien_storage"; public static void persist(String data, Context context) throws IOException { FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE); fos.write(data.getBytes()); fos.close(); } public static String read(Context context) throws IOException { FileInputStream fis = context.openFileInput(FILENAME); StringBuffer fileContent = new StringBuffer(""); byte[] buffer = new byte[1024]; while (fis.read(buffer) != -1) { fileContent.append(new String(buffer)); } return fileContent.toString(); } } 

and here is his test case:

 public class PersistenceManagerTest extends AndroidTestCase { private final String FILENAME_PREFIX = "test."; @Before public void setUp() { MockContentResolver resolver = new MockContentResolver(); RenamingDelegatingContext renamingDelegatingContext = new RenamingDelegatingContext(new MockContext(), getContext(), FILENAME_PREFIX); Context context = new IsolatedContext(resolver, renamingDelegatingContext); setContext(context); } public void testPersistAndRead() throws IOException { String testData = "foobar"; PersistenceManager.persist(testData, getContext()); String result = PersistenceManager.read(getContext()); assertEquals(testData, result); } } 

The test project manifest is as follows:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.devgems.android.kurzparkzonewien.androidtests" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="4" /> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="net.devgems.android.kurzparkzonewien.activities" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <uses-library android:name="android.test.runner" /> </application> </manifest> 

targetPackage is the application with which the Instrumentation object will work, against which the package name is assigned by the element in its manifest file. (Source: http://developer.android.com/guide/topics/manifest/instrumentation-element.html

Package name in my main project

package = "net.devgems.android.kurzparkzonewien.activities"

So this is exactly what targetPackage points to. If I run the “Android JUnit test”, I always get a NoClassDefFoundError, but why? Any ideas? I am using ADT 20.0.3 , Eclipse Juno .

Finally, here is the output of logcat:

09-22 16: 00: 12.745: I / TestRunner (1528): java.lang.NoClassDefFoundError: net.devgems.android.kurzparkzonewien.controller.PersistenceManager 09-22 16: 00: 12.745: I / TestRunner (1528): when net.devgems.android.kurzparkzonewien.androidtests.PersistenceManagerTest.testPersistAndRead (PersistenceManagerTest.java:32) 09-22 16: 00: 12.745: I / TestRunner (1528): with java.lang.reflect.Method.invokeNativeNative 09-22 16: 00: 12.745: I / TestRunner (1528): when java.lang.reflect.Method.invoke (Method.java► 021) 09-22 16: 00: 12.745: I / TestRunner (1528): when junit.framework.TestCase.runTest (TestCase.java:154) 09-22 16: 00: 12.745: I / TestRunner (1528): with junit.framework.TestCase.runBare (TestCase.java:127) 09-22 16: 00: 12.745: I / TestRunner (1528): at junit.framework.TestResult $ 1.protect (TestResult.java:106) 09-22 16: 00: 12.745: I / TestRunner (1528): at junit.framework.TestResult. runProtected (TestResult.java:124) 09-22 16: 00: 12.745: I / TestRunner (1528): pr junit.framework.TestResult.run (TestResult.java:109) 09-22 16: 00: 12.745: I / TestRunner (1528): with junit.framework.TestCase.run (TestCase.java:118) 09-22 16: 00: 12.745: I / TestRunner (1528): with android.test.AndroidTestRunner.runTest (AndroidTestRunner.java:169) 09-22 16: 00: 12.745: I / TestRunner (1528): with android.test.AndroidTestRunner.runTest (AndroidTestRunner.java:154) 09-22 16: 00: 12.745: I / TestRunner (1528): at android.test.InstrumentationTestRunner.onStart (InstrumentationTestRunner.java:430) 09-22 16: 00: 12.745: I / TestRunner (1528): when android.app.Instrumentation $ InstrumentationThread.run (Instrumentation.java:1447) 09-22 16: 00: 12.745: I / TestRunner (1528): ----- end exception -----

+4
source share
1 answer

I have found a solution. But this is actually some kind of workaround, because I can’t imagine that I usually need to behave this way (maybe someone knows a better solution?):

My main project is the Maven project, in this project I need to configure the output folders from / bin ... to / target / classes , target / test classes and target / generated sources . I did this because otherwise my JUnit tests from the main project will not find the latest code changes unless I run mvn install. . If the output folders are target / ... , I don't need to run mvn install to have the latest changes in my tests.
The problem is that the Android test project does not find the compiled sources when they are stored in the main target program of the project. When I set the output folder in the main project to bin and run mvn install , the Android test project can now find the classes. I have to do this only once. When I get back to the target , both of my Android tests still work, and my main JUnit tests run. When I change the methods in the main project, the test project immediately recognizes the changes, so it means that it does not use a binary jar or something (which is really very good, although I do not understand why it finds it now, although I returned it to the goal ?).

[UPDATE]
Adding these two lines to the main pom project to create the partition solves the problem, so I no longer need a workaround.

  <outputDirectory>bin/classes</outputDirectory> <testOutputDirectory>bin/test-classes</testOutputDirectory> 
+2
source

Source: https://habr.com/ru/post/1435672/


All Articles