[英]How to Mock Static Java methods with JRuby and Mocha?
My goal is to unit test legacy Java code, riddled with static utility methods, using JRuby and Mocha. 我的目标是使用JRuby和Mocha对带有静态实用程序方法的遗留Java代码进行单元测试。 Is this possible?
这可能吗?
I am trying to apply similar techniques that are available in JMockit; 我正在尝试应用JMockit中可用的类似技术。 a framework leveraging proxies to change test behavior dynamically.
一个利用代理来动态更改测试行为的框架。 Purists may suggest refactoring out the static methods, but at this point, it's just not possible.
纯粹主义者可能建议重构静态方法,但目前尚不可能。
I put together two unit tests: 我整理了两个单元测试:
Test #1 - Ruby Mocking - my control. 测试#1-Ruby Mocking-我的控制。
Test #2 - Java Mocking - to see if I can accomplish the same in Java. 测试2-Java模拟-看看我是否可以在Java中完成相同的工作。
For both tests, I'm replacing the "getTax" method. 对于这两个测试,我都将替换“ getTax”方法。
Here is the code: 这是代码:
require 'rubygems'
require 'dust'
require 'mocha'
unit_tests do
# Test 1 - Stub out JRuby secondary class and override the "getTax" method
# This is my "control" - I'm overriding the tax multiplier from 1.15 to 1.18.
# It works =)
test "RubyMocking" do
# System Under Test
class RInvoice
def initialize
@util = RInvoiceUtil.new
end
def calculate
@util.getTax * 10.0
end
end
# Dependency
class RInvoiceUtil
# we'll stub out this method and change the tax rate
def getTax
1.15
end
end
invoice = RInvoice.new
# change the tax rate
RInvoiceUtil.any_instance.stubs(:getTax).returns(1.18)
assert_equal(invoice.calculate.to_s, "11.8")
end
end
include Java
require 'rubygems'
require 'dust'
require 'mocha'
require 'invoice.jar'
Invoice = Java::example.Invoice
InvoiceUtil = Java::example.InvoiceUtil
unit_tests do
# Test 2 - Stub out Java class InvoiceUtil and it's *static* getTax method.
# This can be achieved via JMockit, but is it possible in Mocha?
test "JavaMocking" do
invoice = Invoice.new
# this does not work because the ruby objects are only
# proxies to the java objects?
InvoiceUtil.any_instance.stubs(:getTax).returns(1.18)
assert_equal(invoice.calculate, 11.8)
end
end
Test 2 fails with: <11.5> expected but was <11.8> . 测试2失败,并出现: 预期为<11.5>但为<11.8> 。 Ok, so I can't do that.
好的,所以我不能这样做。 Hmm.
嗯 Is the reason this does not work because the ruby objects are only proxies to the java objects?
是不是因为ruby对象只是java对象的代理而不能工作的原因?
package example;
public class Invoice {
public double calculate() {
return InvoiceUtil.getTax() * 10.0;
}
}
public class InvoiceUtil {
public static double getTax() {
return 1.15;
}
}
All I want to do is combine static method mocking with JRuby to leverage (1) easy scripting with (2) flexibile test isolation. 我要做的就是将静态方法模拟与JRuby结合起来,以利用(1)轻松编写脚本以及(2)灵活测试隔离。
Thanks in advance for your responses! 预先感谢您的回复!
I realize this question was asked a long time ago, but I came along a very similar problem and finally got it working. 我知道这个问题是很久以前提出的,但是我遇到了一个非常类似的问题,终于使它起作用了。 I think the problem is in your usage of any_instance...
我认为问题出在您使用any_instance ...
At least in my scenario the solution was to call stubs directly on the class containing the static method: 至少在我的方案中,解决方案是直接在包含静态方法的类上调用存根:
InvoiceUtil.stubs(:getTax).returns(1.18)
I haven't used this myself, but Ola Bini released JtestR a while ago which might be what you're looking for. 我还没有使用过它,但是Ola Bini不久前发布了JtestR ,这可能就是您想要的。 It looks like he has addressed the
any_instance
problem you are seeing above. 看来他已经解决了您在上面看到的
any_instance
问题。 I have no idea how up-to-date JtestR is, but looking at Ola's GitHub account there are some recent commits , so you could be in luck. 我不知道JtestR是什么最新版本,但是查看Ola的GitHub帐户,有一些最新的commit ,所以您可能会很幸运。 I hope this helps.
我希望这有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.