生产代码+测试模块信息=不可能? [英] Production code + Test module-info = Unpossible?

查看:136
本文介绍了生产代码+测试模块信息=不可能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模拟类,该类具有对我从模块中提供的服务的简单实现.我正在使用OpenJDK 11.03,gradle 5.2.1和IntelliJ 2019.2.

在/main/code/myPackage/myService.java中,我有:

package myPackage;
class myService {
   public abstract void someFunction();
}

在我的test/code/somePackage/myMockService中,

package myPackage;
// no import, they're in the same package.
class myMockService extends myService {
   @Override
   public void someFunction() { System.out.prinln("Hello World"); }
}

在我的main/code/module-info.java中

module myModule {
    exports somePackage;
}

我已经在test/code/module-info.java上尝试了几种变体,但没有成功.例如:

// "open module" lets anyone use reflection within (mostly JUnit 5 in my case)
import myPackage.myService;
import myPackage.myMockService;
open module myTestModule { 
    exports myPackage;
    provides myService with myMockService
}

上面的模块信息显示有关模块名称myTestModule与预期名称myModule不匹配",包'myPackage'不可见"(来自myMockModule.java)的错误,解释了模块myModule中声明了包myPackage,但模块myTestModule无法读取它"

另一方面,通过以下模块信息,我得到了另一批错误(在代码下方)

import myPackage.myService;
import myPackage.myMockService;
open module myModule {
    provides myService with myMockService;
}

在没有requires myModule;的情况下,我的测试代码中对主代码分支的每个引用都给出错误:找不到符号". 使用一个requires myModule;,我得到一个错误:涉及myModule的循环依赖关系".

所以...我的测试不能在其他模块中.而且它们不能是同一模块! [删除了一长串的咒语]

  • 如何在测试代码中引入服务的模拟版本,而不是创建完全不同的模块/gradle子项目?

  • 或者这仅仅是不可能的情况,并且当您可以拥有单独的测试模块信息时,您却无法做很多事情?

  • 还是有某种方法可以在运行时动态加载东西,这样我就不必将每个小模拟服务都放在任何模块信息,测试或其他方式中?这样ServiceLoader.load将找到它们.嗯...也许扩展ServiceLoader并将其用法包装在主代码中,以便它将在生产代码或测试代码中使用正确的代码...

解决方案

a)欢迎来到模块化世界中的测试"!

TL; DR https: //sormuras.github.io/blog/2018-09-11-testing-in-the-modular-world.html

拥有一个或多个专用测试模块.用所有的口哨声,阅读module-info.java声明.这些测试模块是您的主要模块的第一个客户端.只要确保您的构建工具在编译和运行测试模块之前就打包了所有主要模块即可.否则,您将不会尽可能接近实际情况来测试您的主要模块-其他人会将您的主要模块用作JAR文件.你也应该这样.这也解决了服务和多版本JAR的所有问题.

现在有趣的部分是:模块内测试,也称为白盒测试.或者测试类型如何驻留在未导出的软件包中或驻留在导出软件包中的软件包专用类型?使用知道在测试编译和/或测试运行时如何将测试模块修补到主模块(反之亦然)的版本.像 pro https://github.com/java9-modularity /gradle-modules-plugin -兑现了在测试运行时传递这些java命令行选项 module-info.test配置文件(我发明了).尽管已经存在完美的DSL,但在这里您基本上通过详细的命令行选项来破坏测试模块的需求:module-info-java ...循环回到a)和模块感知的构建工具.

c) IntelliJ IDEA和Java test 模块正在改善!

I have a mock class with a trivial implementation of a service I provide from a module. I'm using OpenJDK 11.03, gradle 5.2.1 and IntelliJ 2019.2.

In /main/code/myPackage/myService.java I have:

package myPackage;
class myService {
   public abstract void someFunction();
}

And in my test/code/somePackage/myMockService I have

package myPackage;
// no import, they're in the same package.
class myMockService extends myService {
   @Override
   public void someFunction() { System.out.prinln("Hello World"); }
}

In my main/code/module-info.java I have

module myModule {
    exports somePackage;
}

I've tried several variations on a test/code/module-info.java, without success. For example:

// "open module" lets anyone use reflection within (mostly JUnit 5 in my case)
import myPackage.myService;
import myPackage.myMockService;
open module myTestModule { 
    exports myPackage;
    provides myService with myMockService
}

The above module-info spews errors about how "module name myTestModule does not match expected name myModule", "package 'myPackage' is not visible" (from myMockModule.java), explaining "package myPackage is declared in module myModule but module myTestModule does not read it"

On the other hand, with the following module-info, I get a different batch of errors (below the code)

import myPackage.myService;
import myPackage.myMockService;
open module myModule {
    provides myService with myMockService;
}

Without a requires myModule;, every reference to the main code branch from my test code gives an "error: cannot find symbol". With a requires myModule;, I get an "error: cyclic dependence involving myModule".

So... my tests can't be in a different module. AND they can't be the same module! [long string of expletives deleted]

  • How do I introduce a mock version of a service in test code rather than creating an entirely different module/gradle sub-project?

  • Or is this simply a case where that's not possible, and while you can have a separate test module-info, you can't do much with it?

  • Or is there some way to dynamically load things at runtime such that I don't have to put every little mock service in any module-info, test or otherwise? Such that ServiceLoader.load will find them. Hmm... perhaps extend ServiceLoader and wrap its usage in main code such that it'll use the right one either in production code or test code...

解决方案

a) Welcome to "Testing in the Modular World"!

TL;DR https://sormuras.github.io/blog/2018-09-11-testing-in-the-modular-world.html

Having one or more dedicated test modules is good. With all bells-and-whistles, read module-info.java declarations. Those test modules are your main modules' first clients. Just make sure, that your build tool packages all main modules before compiling and running the test modules. Otherwise you don't test your main modules as close as possible to reality -- others will consume your main modules as JAR files. So should you. This solves all issues with services and multi-release JARs as well.

Now the interesting part: in-module testing, also named white box testing. Or how do test types residing non-exported packages or package-private types in exported packages? Either use a build that knows how to patch test modules into main modules (or vice versa) at test compile and/or test runtime. Like pro or Bach.java (which I maintain), or in your case of using Gradle, see b)elow part of this answer.

b) Gradle and Java main, test, ... modules are not friends out-of-the-box, yet

Best plugin-based solution: https://github.com/java9-modularity/gradle-modules-plugin -- which honors the pass theses java command line options at test runtime module-info.test configuration file (which I invented). Here you basically desribe your test module requirements via verbose command line options, although a perfect DSL already exists: module-info-java ... loop back to a) and the module-aware build tools.

c) IntelliJ IDEA and Java test modules are ... improving!

这篇关于生产代码+测试模块信息=不可能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆