My goal is to unit test legacy Java code, riddled with static utility methods, using JRuby and Mocha. Is this possible?
I am trying to apply similar techniques that are available in 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.
Test #2 - Java Mocking - to see if I can accomplish the same in Java.
For both tests, I'm replacing the "getTax" method.
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>. 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?
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.
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...
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)