如何在Gradle中指定类路径顺序

13

我需要控制testRuntime配置中JAR文件的顺序。

我必须确保robolectric-x.x.jar在android.jar之前加载,否则会出现可怕的RuntimeException("Stub!")错误。

我该如何做到这一点?


文档中是否说robolectric jar必须在classpath上的android.jar之前? - c_maker
1
是的,它确实可以。来自Robolectric主页的内容:“故障排除java.lang.RuntimeException: Stub!请确保在类路径中robolectric及其依赖项出现在Android API jar文件之前。” - Olle Hallin
它在Eclipse中工作,因为人们可以在那里明确控制类路径的顺序。该Eclipse项目是由Gradle生成的。 - Olle Hallin
你可以通过在gradle依赖中进行排序来解决它,但要注意两个优先级更高的规则!https://dev59.com/dFwZ5IYBdhLWcg3wPOJM#38743046 - Gangnus
2个回答

13

以下是我为在我的Android应用中使用RoboGuice运行Robolectric测试而编写的完整build.gradle文件:

apply plugin: 'java'

androidJar = new File(System.getenv('ANDROID_HOME'), '/platforms/android-7/android.jar')

configurations { robo }

dependencies {
    robo('com.pivotallabs:robolectric:1.0-RC1')
    testCompile('org.roboguice:roboguice:1.1.2')
    testCompile('junit:junit:4.8.2')
    testCompile project (':app')
    testCompile files(androidJar)
}

sourceSets.test.compileClasspath = configurations.robo + sourceSets.test.compileClasspath
sourceSets.test.runtimeClasspath = configurations.robo + sourceSets.test.runtimeClasspath

test {
    excludes = ['**/MyRobolectricTestRunner.class']
}
我必须为测试运行器添加一个排除项,否则Gradle将会抛出异常。
我的MyRobolectricTestRunner.java文件看起来像这样:
package com.acme.myapp;

import java.io.File;
import org.junit.runners.model.InitializationError;
import roboguice.application.RoboApplication;
import roboguice.inject.ContextScope;
import com.google.inject.Injector;
import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.RobolectricTestRunner;

public class MyRobolectricTestRunner extends RobolectricTestRunner {
    public MyRobolectricTestRunner(Class<?> testClass) throws InitializationError {
        // Tell Robolectric where to find AndroidManifest.xml and res/
        super(testClass, new File("../app"));
    }

    /**
     * Enable injection into tests as well...
     */
    @Override
    public void prepareTest(Object test) {
        RoboApplication myApplication = (RoboApplication) Robolectric.application;
        Injector injector = myApplication.getInjector();
        ContextScope contextScope = injector.getInstance(ContextScope.class);
        contextScope.enter(myApplication);
        injector.injectMembers(test);
    }

}

以下是一个示例测试,说明了注入的情况:

package com.acme.myapp;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import roboguice.inject.InjectResource;

@RunWith(MyRobolectricTestRunner.class)
public class StringFormattingTest {

    @InjectResource(R.string.info_pending_amount)
    private String pendingAmountPattern;

    @Test
    public void testFormatInfoPendingAmount() {
        String s = String.format(pendingAmountPattern, 20.0d, "EUR");
        assertEquals("Only a part of your stake (20,00 EUR) was accepted", s);
    }

}

你如何通过自己的settings.gradle引用:app?:app是否还公开其自身的依赖项供测试使用? - Moritz
我们能在GitHub上获取一个简单的示例吗? - Gary

4
这可能有效:
configurations { robo }

dependencies {
  robo ...
  testRuntime ...
}

sourceSets.test.runtimeClasspath = configurations.robo + sourceSets.test.runtimeClasspath

我不得不将robo加入编译类路径。 - Olle Hallin
1
@Peter 你知道如何在这种情况下更改类路径的顺序吗? - JJD

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