Rspec,Rails:如何测试控制器的私有方法?

pet*_*hka 123 rspec ruby-on-rails

我有控制器:

class AccountController < ApplicationController
  def index
  end

  private
  def current_account
    @current_account ||= current_user.account
  end
end
Run Code Online (Sandbox Code Playgroud)

如何current_account使用rspec 测试私有方法?

PS我使用Rspec2和Ruby on Rails 3

mon*_*cle 191

使用#instance_eval

@controller = AccountController.new
@controller.instance_eval{ current_account }   # invoke the private method
@controller.instance_eval{ @current_account }.should eql ... # check the value of the instance variable
Run Code Online (Sandbox Code Playgroud)

  • 如果您愿意,还可以说:@ controller.send(:current_account). (92认同)
  • 我认为你是错误的答案或者没有回答这个问题.这个答案是正确的,不应该被低估.如果您不同意测试私有方法的做法,请将其放在评论中,因为它是好的信息(尽可能多),然后人们可以对该评论进行投票,这仍然显示您的观点,而不会不必要地低估一个完美有效的答案. (34认同)
  • Srdjan Pejic你能详细说明为什么不应该测试私有方法吗? (24认同)
  • Ruby允许你使用send调用私有方法,但这并不一定意味着你应该.通过测试这些方法的公共接口来测试私有方法.这种方法可行,但并不理想.如果方法是在一个包含在控制器中的模块中,那就更好了.然后它也可以独立于控制器进行测试. (13认同)
  • 即使这个答案在技术上回答了这个问题,但我还是低估了它,因为它违反了测试中的最佳实践.不应该测试私有方法,只是因为Ruby使您能够绕过方法可见性,并不意味着您应该滥用它. (9认同)
  • 提升它b/c人们不应该讲好/坏做法,这个人只需要测试他的私人方法.我去过那儿. (5认同)
  • @SrdjanPejic我同意你不应该测试私有方法NORMALLY,但是你不应该在rails控制器上公开除了动作之外的任何东西,有时在before_filter或类似的东西上调用私有方法.恕我直言,如果它不是一个简单的案例,它应该进行测试. (2认同)

小智 37

我用send方法.例如:

event.send(:private_method).should == 2
Run Code Online (Sandbox Code Playgroud)

因为"发送"可以调用私有方法


Rya*_*igg 23

current_account方法在哪里使用?它有什么用途?

通常,您不测试私有方法,而是测试调用私有方法的方法.

  • 根据我的理解,如果你想在单元测试中实现真正的粒度,私有方法也应该进行测试.如果要重构代码,单元测试也必须进行相应的重构.这可以确保您的新代码也能按预期工作. (9认同)
  • @Pullets我不同意,你应该测试API的公共方法,它将调用私有方法,正如我的原始答案所说.您应该测试您提供的API,而不是您可以看到的私有方法. (6认同)
  • 理想情况下,应该测试每种方法.我已经使用了subject.send和subject.instance_eval在rspec上取得了很大的成功 (5认同)
  • 我同意@Ryan Bigg.您不测试私有方法.这将删除您重构或更改所述方法的实现的能力,即使该更改不会影响代码的公共部分.请在编写自动化测试时阅读最佳实践. (5认同)
  • 嗯,也许我错过了什么.我写的课程比私人课程有更多私人方法.仅通过公共API进行测试将导致列出数百个不会镜像他们正在测试的代码的测试. (4认同)

Lor*_*lor 8

你应该没有直接测试你的私有方法,他们能够而且应该通过公共方法行使代码间接测试.

这使您可以在不必更改测试的情况下更改代码的内部.


zis*_*she 5

您可以将私有或受保护的方法设为公共:

MyClass.send(:public, *MyClass.protected_instance_methods) 
MyClass.send(:public, *MyClass.private_instance_methods)
Run Code Online (Sandbox Code Playgroud)

只需将此代码放在您的测试类中,替换您的类名。如果适用,请包括命名空间。