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

发布于 2024-12-18 10:58:00 字数 1743 浏览 0 评论 0原文

我是 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

报告者期望的“配置文件”类型是 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

有谁知道我如何对 results 方法的调用存根我新创建的班级?

任何指示将不胜感激!

〜斯图

I'm new to TDD and metaprogramming so bear with me!

I have a Reporter class (to wrap the Garb ruby gem) that will generate a new report class on-the-fly and assign it to a GoogleAnalyticsReport module when I hit method_missing. The main gist is as follows:

# 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

The type of 'profile' that the Reporter expects is a Garb::Management::Profile.

In order to test some of my private methods on this Reporter class (such as valid_method_name? or build_class_name), I believe I want to mock the profile with rspec as it's not a detail that I'm interested in.

However, the call to klass.results(@profile) - is executing and killing me, so I haven't stubbed the Garb::Model that I'm extending in my meta part.

Here's how I'm mocking and stubbing so far... the spec implementation is of course not important:

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

Does anyone know how I can stub the call to the results method on my newly created class?

Any pointers will be greatly appreciated!

~ Stu

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酒与心事 2024-12-25 10:58:00

而不是:

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

我认为您想要执行以下操作:

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

这将删除 Garb::Model 的任何实例以返回结果。您需要这样做,因为您实际上并未将 @mock_model 传递到任何将使用它的类/方法中,因此您必须更通用一些。

Instead of:

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

I think you want to do:

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

This will stub out any instance of Garb::Model to return results. You need to do this because you are not actually passing @mock_model into any class/method that will use it so you have to be a bit more general.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文