【问题标题】:How to Mock Static Java methods with JRuby and Mocha?如何使用 JRuby 和 Mocha 模拟静态 Java 方法?
【发布时间】:2010-12-02 03:05:41
【问题描述】:

我的目标是使用 JRuby 和 Mocha 对充满静态实用方法的遗留 Java 代码进行单元测试。这可能吗?

我正在尝试应用 JMockit 中可用的类似技术;一个利用代理动态改变测试行为的框架。纯粹主义者可能会建议重构出静态方法,但在这一点上,这是不可能的。

我将两个单元测试放在一起:

测试 #1 - Ruby Mocking - 我的控制。
测试 #2 - Java Mocking - 看看我是否可以在 Java 中完成同样的任务。

对于这两个测试,我将替换“getTax”方法。

代码如下:

测试 1

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

测试 2

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

测试 2 失败: 预期但为 。好的,所以我不能那样做。唔。这不起作用的原因是因为 ruby​​ 对象只是 java 对象的代理吗?

Java 源代码

package example;
public class Invoice {
    public double calculate() {
        return InvoiceUtil.getTax() * 10.0;
    }
}

public class InvoiceUtil {
    public static double getTax() {
        return 1.15;
    }
}

总结

我想做的就是将静态方法模拟与 JRuby 结合起来,以利用 (1) 简单的脚本编写和 (2) 灵活的测试隔离。

提前感谢您的回复!

【问题讨论】:

    标签: java unit-testing static jruby mocha.js


    【解决方案1】:

    我意识到这个问题是很久以前提出的,但我遇到了一个非常相似的问题,终于让它工作了。我认为问题在于您对 any_instance 的使用...

    至少在我的场景中,解决方案是直接在包含静态方法的类上调用存根:

    InvoiceUtil.stubs(:getTax).returns(1.18)
    

    【讨论】:

      【解决方案2】:

      我自己没有使用过这个,但Ola Bini 不久前发布了JtestR,这可能是您正在寻找的。看起来他has addressed 是您在上面看到的any_instance 问题。我不知道 JtestR 有多最新,但看看 Ola 的 GitHub 帐户,有一些 recent commits,所以你可能很幸运。我希望这会有所帮助。

      【讨论】:

      • 感谢 floehopper 的指点。我一定会检查 JtestR。在进一步考虑它时,我可以看到为什么测试框架(在 Java vm 中)需要支持存根/替换。特别是如果我们谈论的是对给定被测单元的直接依赖关系。
      • 进一步阅读后,我了解到这两个对象生命周期虽然能够相互引用,但不一定在它们的创建/依赖关系中具有挂钩。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      相关资源
      最近更新 更多