在尝试在Android Studio上运行单元测试时出现NoClassDefFoundError错误

13

我想为我的安卓应用程序创建一些简单的测试,但是在运行测试时遇到了问题。我一直在尝试运行测试时都会收到NoClassDefFound错误,但是我似乎无法找出其原因。如果可以,请帮忙查看一下。

编辑:这是项目结构的图片:

Link

以下是我一直收到的错误信息:

junit.framework.AssertionFailedError: Exception in constructor: testScanResultNotNull (java.lang.NoClassDefFoundError: nl.hanze.myhealth.ScanResultActivity
at nl.hanze.myhealth.CameraTest.<init>(CameraTest.java:14)
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
at junit.runner.BaseTestRunner.getTest(BaseTestRunner.java:118)
at android.test.AndroidTestRunner.getTest(AndroidTestRunner.java:149)
at android.test.AndroidTestRunner.setTestClassName(AndroidTestRunner.java:57)
at android.test.suitebuilder.TestSuiteBuilder.addTestClassByName(TestSuiteBuilder.java:80)
at android.test.InstrumentationTestRunner.parseTestClass(InstrumentationTestRunner.java:443)
at android.test.InstrumentationTestRunner.parseTestClasses(InstrumentationTestRunner.java:424)
at android.test.InstrumentationTestRunner.onCreate(InstrumentationTestRunner.java:370)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4435)
at android.app.ActivityThread.access$1300(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)

相机测试

package nl.hanze.myhealth;

import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;

    public class CameraTest extends ActivityInstrumentationTestCase2<ScanResultActivity> {

        ScanResultActivity mActivity;

        public CameraTest(){
            super(ScanResultActivity.class);
        }

        @Override
        protected void setUp()throws Exception{
            super.setUp();
            mActivity = getActivity();
        }

        @SmallTest
        public void testScanResultNotNull(){
            boolean test = mActivity.generateScanResult();
            assertNotNull(test);
        }

        @Override
        protected void tearDown() throws Exception{
            super.tearDown();
        }
    }

扫描结果活动

package nl.hanze.myhealth;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

import java.util.Random;


    public class ScanResultActivity extends Activity {

        Random rand = new Random();

        public ScanResultActivity(){

        }

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

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.scan_result, menu);
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }

        protected boolean generateScanResult(){
            boolean positive_scanresult;
            int max = 10;
            int min = 1;
            int randomNum = rand.nextInt((max - min) + 1) + min;
            if(randomNum >= 6){
                positive_scanresult = true;
            }else{
                positive_scanresult = false;
            }
            return positive_scanresult;
        }
    }

你是在运行Android测试而不是JUnit测试吗? - dragi
@helleye,我相信我正在运行Android测试。 - Anubis
从代码中看,你的测试类在 package nl.hanze.myhealth; 中,而不是在测试包中。 - dragi
@helleye 我在原帖中附上了结构的图片。androidTest文件夹是由Android Studio生成的。 - Anubis
错误信息为:(java.lang.NoClassDefFoundError: nl.hanze.myhealthtests.ScanResultActivity)。那么你在哪里定义了 nl.hanze.myhealthtests - dragi
@helleye 嗯,事情是这样的:我尝试将包含测试的包重命名为另一个名称,但由于某种原因,这最终导致两个包都被重命名为healthtests。错误只是因为我仍然将两个包重命名为healthtests时出现的。 - Anubis
3个回答

11

我也遇到过这个问题,不确定是否和你的原因相同,但是对于我来说解决方法很简单:文件->无效缓存/重启


重新同步Gradle也解决了我的问题。 - Weiyi

8
我在Android Studio中运行测试(JUnit/Robolectric3/Gradle)时突然出现了这个错误,但不知道原因。我能够单独运行测试文件,但是当所有测试在一个包中运行时,就会出现NoClassDefFoundError异常。
结果发现运行时的类路径没有正确加载类。这个问题在另一台电脑上无法重现。
为了解决这个问题,我删除了项目的.idea文件夹和.iml文件,重新将整个Gradle项目导入到Android Studio中。然后它就正常工作了!

谢谢您的建议,另外我发现一些模块依赖项可能配置不正确。请参见 https://stackoverflow.com/questions/37319185 - TheIT

5

1) 将您的测试放入包中nl.hanze.myhealth.tests。您可以使用Android Studio或手动完成:

  • 在...\app\src\androidTest\java\nl\hanze\myhealth\内创建一个新文件夹tests
  • 将ApplicationTest.java和CameraTest.java移动到...\app\src\androidTest\java\nl\hanze\myhealth\tests\内
  • 在每个Java测试文件中重命名软件包名称为
    package nl.hanze.myhealth.tests;

2) 在应用程序的build.gradle中,您需要拥有:

defaultConfig {
    applicationId "nl.hanze.myhealth"
    testApplicationId "nl.hanze.myhealth.tests"
    ...
}

重新构建并运行即可。这应该足够了。


1
祝你测试编写顺利。最近我遇到了很多问题 :) - dragi
3
我不明白为什么需要重命名测试包,以及为什么这样做会有效。通常情况下这是不必要的,因为测试通常与被测试的类在同一个包中。 - Adil Hussain
@AdilHussain,是的,我最近几次编写测试时没有重命名测试包也可以正常工作。我猜测在此期间工具链进行了一些更新。 - dragi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接