我这里有一个有趣的 JUnit 问题 (JUnit 4.12)。我有一个只有静态方法的基类。由于它们的使用方式,它们必须是静态的。我从基类继承其他类。所以,如果基类是 Base,我们就有 ChildA 和 ChildB。
大部分方法都包含在基类中,但它必须知道它实际上是哪个子类(仅仅调用基类方法是无效的)。这是通过基类中的静态数据成员完成的:
public class Base {
protected static ChildType myType = ChildType.Invalid;
...
}
每个 child 通过静态初始化器设置数据成员,因此:
static {
myType = ChildType.ChildA;
}
然后当调用方法时,基类知道它是什么类型并加载适当的配置(类型实际上是一个配置名称)。
这一切在运行应用程序时都能完美运行。在调试器中单步执行它并通过日志消息,我可以看到设置了适当的类型,并且方法根据子类型加载了适当的配置。
问题出现在使用JUnit 时。我们有一些 JUnit 测试来测试每个基类方法。由于只调用基类的方法是无效的,我们调用子类的方法,因此:
bool result = ChildA.methodTwo();
这个“总是失败”。为什么?静态初始值设定项永远不会被调用。当将代码作为应用程序运行时,它会被调用,大家都很高兴。当我将它作为 JUnit 测试运行时,静态初始值设定项被跳过并且方法具有无效数据。 JUnit 做了什么跳过了静态初始值设定项?有解决办法吗?
详情
实际上,我们并没有调用我上面发布的方法。我只是想让这个例子尽可能清楚。实际上,我们有一个使用 Jersey 框架编写的 Web 服务。调用的方法是 REST 端点之一。
@POST
@Produces(MediaType.TEXT_PLAIN)
public String methodPost() {
...
return new String( itWorked ? "success" : "fail" );
}
我们这样调用它(抱歉语法丑陋,这就是它的工作方式):
@Test
public void testThePost() throws Exception {
javax.ws.rs.core.Response response = target("restapi/").request().post(Entity.entity(null, MediaType.TEXT_PLAIN));
assertEquals( 200, response.getStatus() );
}
所有的 GET 测试都有效,静态初始化程序在所有这些测试上都被调用。只是这个 POST 失败了,并且仅在运行 JUnit 测试时失败。
最佳答案
您正在尝试为静态方法实现多态行为,这是一种存在于其他编程语言中但在 Java 中缺失的语言特性。
[
myTypeis] a protected member of the base class
依靠静态初始值设定项来设置基类中的静态字段是非常脆弱的,因为多个子类“竞争”基类中的单个字段。这会将基类的行为“锁定”到其初始化程序最后运行的子类所期望的行为中。除其他坏事外,它否认了与 Base 一起使用多个子类的可能性。类,并使 ChildA.methodTwo() 成为可能运行为 ChildB.methodTwo() 设计的功能.事实上,没有ChildA.methodTwo()和 ChildB.methodTwo() , 只有 Base.methodTwo()依赖于静态初始化序列为其准备的信息。
这个问题有多种解决方案。一种可能性是通过 Class<Child###>对象到基类的方法:
class Base {
public static void method1(Class childConfig, String arg) {
...
}
public static void method2(Class childConfig, int arg1, String arg2) {
...
}
}
现在调用者需要改变
ChildA.method1("hello");
ChildA.method2(42, "world");
到
Base.method1(ChildA.class, "hello");
Base.method2(ChildA.class, 42, "world");
另一种解决方案是用非静态替换静态实现,并使用“常规”多态行为与在派生类中创建的单例相结合:
class Base {
protected Base(Class childConfig) {
...
}
public void method1(String arg) {
...
}
public void method2(int arg1, String arg2) {
...
}
}
class ChildA extends Base {
private static final Base inst = new ChildA();
private ChildA() {
super(ChildA.class);
}
public static Base getInstance() {
return inst;
}
... // Override methods as needed
}
class ChildB extends Base {
private static final Base inst = new ChildB();
private ChildB() {
super(ChildB.class);
}
public static Base getInstance() {
return inst;
}
... // Override methods as needed
}
并调用
ChildA.getInstance().method1("hello");
ChildA.getInstance().method2(42, "world");
关于java - 静态初始化程序在 JUnit 测试期间不运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46914409/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到rubygems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此