【问题标题】:Is it possible to use ruby refinements to change the behavior of a controller action in tests?是否可以使用 ruby​​ 改进来更改测试中控制器操作的行为?
【发布时间】:2017-05-18 16:00:16
【问题描述】:

是否可以使用细化功能来存根控制器操作?

我在“my_controller_refinement.rb”中定义细化

require "my_controller"

module MyControllerRefinement
  refine MyController do
    def create_item(my_object = {})
      return "test_id"
    end
  end
end

并在测试中使用如下-

require_relative "my_controller_refinement"

class MyControllerTest < ActionController::TestCase
  using MyControllerRefinement

  test "get item" do
    post :create { my_object: { name: "Test", id: "test_id" } }
    # Post redirects to the show page
    assert_redirected_to action: "show", id: "test_id"
  end
end

测试目录为 -

test/
  -->  my_controller_refinement.rb
  -->  my_controller_test.rb

但是细化并没有开始,实际的控制器动作似乎被调用了。

我是否遗漏了什么,或者不能将改进用于这种“存根”?

【问题讨论】:

标签: ruby-on-rails ruby stubbing refinements


【解决方案1】:

由于Refinements 目前的工作方式,这将不起作用。文档(引用如下)具有完整的独家新闻,但本质上,改进的范围非常狭窄。

您只能在顶层激活细化,而不是在任何类、模块或方法范围内。您可以在传递给 Kernel#eval 的字符串中激活细化,该字符串在顶层进行评估。细化一直有效,直到文件结束或 eval 字符串结束。

细化在范围上是词法的。当控制转移到范围之外时,细化被停用。这意味着如果您需要或加载文件或调用在当前范围之外定义的方法,则优化将被停用。

【讨论】:

  • 如果我错了,请纠正我,但从文档来看,这是我的理解 c.rb --&gt; my_controller.rb, m.rb --&gt; my_controller_refinement.rb, m_user.rb --&gt; my_controller_test.rb 您是否建议我将 using MyControllerRefinement 移到课堂外? (我也试过了,好像不行)
  • 或者可能是因为ActionController::TestCase 词法范围不符合预期,因此无法进行细化?
  • “你是在建议我将 using MyControllerRefinement 移到课堂之外吗?”不,我以“这行不通”开头。我不知道你为什么认为这可能是建议的。根据文档,这是行不通的。 1)您不能在类内激活细化,2)当您调用另一个方法时,细化将被停用。由于您没有直接从您的测试中调用@controller.new(库是),因此优化不会处于活动状态。
  • 由于您粘贴的简介包含顶级激活和词法范围,我只是想了解您的建议。感谢您澄清这一点!正如我之前评论的那样,我有一种预感,即词法范围是不正确的。将尝试对此进行探索。
【解决方案2】:

正如另一个答案所提到的,细化是词法范围的,这意味着它们仅在 classend 之间的空间中有效。我可以举个例子:

class OrigClass
  def test_method
    # checks if some methods are defined and calls them if they are
    puts (!! defined? patch_method_1) && patch_method_1
    puts (!! defined? patch_method_2) && patch_method_2
  end
  # the refinement will attempt to overwrite this method
  def patch_method_1; 0; end
end

puts OrigClass.new.test_method # => 0 false

module Refinement
  refine OrigClass do
    # this method is already defined on OrigClass
    def patch_method_1; 1; end
    # this one is not
    def patch_method_2; 2; end
  end
end

# re-open the class to add the refinement
class OrigClass
  using Refinement
  puts new.test_method # => 0 false
  puts new.patch_method_1 # => 1
  puts new.patch_method_2 # => 2
end

puts OrigClass.new.test_method # => 0 false

由于词法作用域,对test_method 的最后两个调用不使用细化方法。这没有使用您的确切用例(控制器操作),但它是相同的概念,并表明改进证明很难以这种方式使用。

【讨论】:

  • 很好的例子@max-pleaner,但我相信他们的行为就像他们应该做的那样!假设在您重新打开课程时,您将课程重命名为 OrigClassTest 并执行 puts OrigClass.new.patch_method_1,您将看到细化开始。在我的示例中,重新打开课程以添加细化对应于使用细化的测试。
  • 也许我缺少的是使用超类 ActionController::TestCase 生成测试的方式,因此我需要重新考虑我尝试改进控制器操作的方式。
  • 问题是,您的测试用例没有显式调用您通过细化更改的方法。大概是在某个地方在幕后调用的,所以精炼不会激活。
猜你喜欢
  • 2012-02-15
  • 1970-01-01
  • 2014-05-11
  • 1970-01-01
  • 1970-01-01
  • 2020-09-05
  • 2011-02-06
  • 2013-06-06
  • 1970-01-01
相关资源
最近更新 更多