使用rspec在ruby元编程中模拟动态生成的类

时间:2011-11-29 10:52:38

标签: ruby rspec mocking metaprogramming

我是TDD 元编程的新手,所以请耐心等待!

我有一个Reporter类(包装Garb ruby​​ gem),它将动态生成一个新的报告类,并在我点击method_missing时将其分配给GoogleAnalyticsReport模块。主要内容如下:

Reporter.rb

def initialize(profile)
        @profile = profile
    end

def method_missing(method, *args)

        method_name = method.to_s
        super unless valid_method_name?(method_name)

        class_name = build_class_name(method_name)
        klass = existing_report_class(class_name) || build_new_report_class(method_name, class_name)
        klass.results(@profile)
    end

def build_new_report_class(method_name, class_name)
        klass = GoogleAnalyticsReports.const_set(class_name, Class.new)
        klass.extend Garb::Model
        klass.metrics << metrics(method_name)
        klass.dimensions << dimensions(method_name)
        return klass
    end

Reporter期望的'profile'类型是Garb :: Management :: Profile。

为了在这个Reporter类上测试我的一些私有方法(例如valid_method_name?或build_class_name),我相信我想用rspec模拟配置文件,因为它不是我感兴趣的细节。

然而,调用klass。结果(@ profile) - 正在执行并杀死我,所以我没有删除我在元部分中扩展的Garb :: Model。

到目前为止,我正在嘲笑和抄袭......规范实施当然不重要:

describe GoogleAnalyticsReports::Reporter do
before do

@mock_model = mock('Garb::Model')
@mock_model.stub(:results) # doesn't work!

@mock_profile = mock('Garb::Management::Profile')
@mock_profile.stub!(:session)

@reporter = GoogleAnalyticsReports::Reporter.new(@mock_profile)

end

describe 'valid_method_name' do
it 'should not allow bla' do
    @reporter.valid_method_name?('bla').should be_false
end


end
end

有没有人知道我如何在新创建的类上存根调用 结果 方法?

任何指针都将非常感谢!

~Stu

1 个答案:

答案 0 :(得分:2)

而不是:

@mock_model = mock('Garb::Model')
@mock_model.stub(:results) # doesn't work!

我想你想做:

Garb::Model.any_instance.stub(:results)

这将存根Garb :: Model的任何实例以返回结果。你需要这样做,因为你实际上并没有将@mock_model传递给任何会使用它的类/方法,因此你必须更加通用。