Android 如何覆盖Robolectric运行时依赖库URL?

Android 如何覆盖Robolectric运行时依赖库URL?,android,android-gradle-plugin,robolectric,Android,Android Gradle Plugin,Robolectric,我们正在尝试使用我们自己的内部Nexus存储库中的org.roblectric:roblectric:3.0依赖项。问题是Robolectric试图在运行时从公共存储库()加载一些依赖项,并忽略build.gradle中的任何存储库覆盖 由于我们无法从内部网访问该公共位置,因此我的测试在尝试加载该依赖项后超时: [警告]无法获取资源 “org.roblectric:android all:jar:5.0.0_r2-roblectric-1”来自 存储库类型(): 传输文件时出错:操作超时 的底部

我们正在尝试使用我们自己的内部Nexus存储库中的
org.roblectric:roblectric:3.0
依赖项。问题是Robolectric试图在运行时从公共存储库()加载一些依赖项,并忽略build.gradle中的任何存储库覆盖

由于我们无法从内部网访问该公共位置,因此我的测试在尝试加载该依赖项后超时:

[警告]无法获取资源 “org.roblectric:android all:jar:5.0.0_r2-roblectric-1”来自 存储库类型(): 传输文件时出错:操作超时

的底部部分建议将其添加到Gradle配置中以覆盖URL:

android {
  testOptions {
    unitTests.all {
      systemProperty 'robolectric.dependency.repo.url', 'https://local-mirror/repo'
      systemProperty 'robolectric.dependency.repo.id', 'local'
    }
  }
}
不幸的是,我已经测试过了,我从来没有看到系统属性被设置。我已经从自定义Robolectric runner(扩展了RobolectricGradleTestRunner)内部打印出来,并且该系统属性仍然设置为null

System.out.println("robolectric.dependency.repo.url: " + System.getProperty("robolectric.dependency.repo.url"));
我还尝试做了类似的事情(但该方法在
RobolectricGradeleteStrunner
中不存在重写),我还尝试直接在自定义Robolectric runner中设置系统属性,但似乎没有帮助

@Config(constants = BuildConfig.class)
public class CustomRobolectricRunner extends RobolectricGradleTestRunner {
    private static final String BUILD_OUTPUT = "build/intermediates";

    public CustomRobolectricRunner(Class<?> testClass) throws InitializationError {
        super(testClass);

        System.setProperty("robolectric.dependency.repo.url", "https://nexus.myinternaldomain.com/content");
        System.setProperty("robolectric.dependency.repo.id", "internal");

        System.out.println("robolectric.dependency.repo.url: " + System.getProperty("robolectric.dependency.repo.url"));
    }
@Config(constants=BuildConfig.class)
公共类CustomRobolectricRunner扩展了RobolectricGradleTestRunner{
私有静态最终字符串BUILD\u OUTPUT=“BUILD/intermediates”;
公共CustomRobolectricRunner(类testClass)引发初始化错误{
超级(测试类);
System.setProperty(“roblectric.dependency.repo.url”https://nexus.myinternaldomain.com/content");
System.setProperty(“roblectric.dependency.repo.id”,“internal”);
System.out.println(“roblectric.dependency.repo.url:+System.getProperty(“roblectric.dependency.repo.url”);
}

似乎确实确认了这些系统属性的存在。

虽然无法修复直接使用属性的问题,但另一种方法是覆盖
RobolectrictTestRunner
子类中的
getJarResolver()
,并将其指向您的工件主机:

public final class MyTestRunner extends RobolectricTestRunner {
  public MyTestRunner(Class<?> testClass) throws InitializationError {
    super(testClass);
  }

  @Override protected DependencyResolver getJarResolver() {
    return new CustomDependencyResolver();
  }

  static final class CustomDependencyResolver implements DependencyResolver {
    private final Project project = new Project();

    @Override public URL[] getLocalArtifactUrls(DependencyJar... dependencies) {
      DependenciesTask dependenciesTask = new DependenciesTask();
      RemoteRepository repository = new RemoteRepository();
      repository.setUrl("https://my-nexus.example.com/content/groups/public");
      repository.setId("my-nexus");
      dependenciesTask.addConfiguredRemoteRepository(repository);
      dependenciesTask.setProject(project);
      for (DependencyJar dependencyJar : dependencies) {
        Dependency dependency = new Dependency();
        dependency.setArtifactId(dependencyJar.getArtifactId());
        dependency.setGroupId(dependencyJar.getGroupId());
        dependency.setType(dependencyJar.getType());
        dependency.setVersion(dependencyJar.getVersion());
        if (dependencyJar.getClassifier() != null) {
          dependency.setClassifier(dependencyJar.getClassifier());
        }
        dependenciesTask.addDependency(dependency);
      }
      dependenciesTask.execute();

      @SuppressWarnings("unchecked")
      Hashtable<String, String> artifacts = project.getProperties();
      URL[] urls = new URL[dependencies.length];
      for (int i = 0; i < urls.length; i++) {
        try {
          urls[i] = Util.url(artifacts.get(key(dependencies[i])));
        } catch (MalformedURLException e) {
          throw new RuntimeException(e);
        }
      }
      return urls;
    }

    @Override public URL getLocalArtifactUrl(DependencyJar dependency) {
      URL[] urls = getLocalArtifactUrls(dependency);
      if (urls.length > 0) {
        return urls[0];
      }
      return null;
    }

    private String key(DependencyJar dependency) {
      String key =
          dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getType();
      if (dependency.getClassifier() != null) {
        key += ":" + dependency.getClassifier();
      }
      return key;
    }
  }
}
公共最终类MyTestRunner扩展了RobolectrictTestRunner{
公共MyTestRunner(类testClass)引发初始化错误{
超级(测试类);
}
@重写受保护的DependencyResolver getJarResolver(){
返回新的CustomDependencyResolver();
}
静态最终类CustomDependencyResolver实现DependencyResolver{
私人最终项目=新项目();
@重写公共URL[]GetLocalArtifactURL(DependencyJar…dependencies){
DependenciesTask DependenciesTask=新的DependenciesTask();
RemoteRepository repository=新的RemoteRepository();
repository.setUrl(“https://my-nexus.example.com/content/groups/public");
setId(“我的关系”);
dependenciesTask.addConfiguredRemoteRepository(存储库);
dependenciesTask.setProject(项目);
for(DependencyJar DependencyJar:dependencies){
依赖项=新依赖项();
dependency.setArtifactId(dependencyJar.getArtifactId());
dependency.setGroupId(dependencyJar.getGroupId());
setType(dependencyJar.getType());
dependency.setVersion(dependencyJar.getVersion());
if(dependencyJar.getClassifier()!=null){
dependency.setClassifier(dependencyJar.getClassifier());
}
dependenciesTask.addDependency(dependency);
}
dependenciesTask.execute();
@抑制警告(“未选中”)
Hashtable artifacts=project.getProperties();
URL[]URL=新URL[dependencies.length];
for(int i=0;i0){
返回URL[0];
}
返回null;
}
私有字符串密钥(DependencyJar dependency){
串键=
dependency.getGroupId()+“:”+dependency.getArtifactId()+“:”+dependency.getType();
if(dependency.getClassifier()!=null){
键+=”:“+dependency.getClassifier();
}
返回键;
}
}
}

需要注意的是,这依赖于两个内部Robolectric类,因此升级版本时应小心。

您可以设置
RoboSetting
的属性
mavenRepositoryId
mavenRepositoryUrl

例如:

public class CustomRobolectricRunner extends RobolectricGradleTestRunner {

    static {
        RoboSettings.setMavenRepositoryId("my-nexus");
        RoboSettings.setMavenRepositoryUrl("https://my-nexus.example.com/content/groups/public");
    }


    ...
}
根据,一个修复方法是在
~\.m2
文件夹中配置
settings.xml

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <mirrors>
        <mirror>
            <id>jcenter</id>
            <name>JCenter Remote</name>
            <mirrorOf>*</mirrorOf>
            <url>https://www.example.com/artifactory/jcenter-remote/</url>
        </mirror>
    </mirrors>
</settings>

jcenter
JCenter远程
*
https://www.example.com/artifactory/jcenter-remote/
*
似乎需要强制Maven将所有存储库请求重定向到一个远程服务器。有关Maven中镜像设置的更多详细信息,请参阅


我发现使用Sonatype的remote是不够的,您应该使用JCenter或Maven Central的remote来获取所有可传递的依赖项。

在撰写本文时,以前的答案现在已经过时了。如果您引用最新的答案,您需要覆盖
robolectric.dependency.repo.url
属性我喜欢这样:

android {
  testOptions {
    unitTests.all {
      systemProperty 'robolectric.dependency.repo.url', 'https://local-mirror/repo'
      systemProperty 'robolectric.dependency.repo.id', 'local'
    }
  }
}

原始问题中提到了这个精确的解决方案和链接。你是对的。我当时太专注于阅读和尝试不同的答案了,我错过了原始问题中的这一部分。我道歉。奇怪的是,这是唯一对我有效的方法。
RoboSettings
被弃用,这些方法不再存在t、 我检查了4.3.1Hi@Alix版本。请查看lo