【问题标题】:Is there a better way to test that a script is being called in a controller other than expect_any_instance_of(#{ControllerClass}).to receive?除了 expect_any_instance_of(#{ControllerClass}).to 之外,有没有更好的方法来测试在控制器中调用脚本?
【发布时间】:2020-01-24 16:27:07
【问题描述】:

我对使用 RSpec 还很陌生,所以还有很多我不知道的地方。我目前正在研究指定按下按钮时应该运行脚本的部分功能。脚本目前在一个控制器中调用,不知道有没有好的测试方法。

我正在使用

expect_any_instance_of(ConfigurationsController)
  .to receive(:system)
  .with('sh bin/resque/kill_resque_workers')
  .and_return(true)

在功能规范中它可以工作,但 rubocop 抱怨使用 expect_any_instance_of 并且我被告知只有在没有更好的方法时才使用该方法。

有没有更好的测试方法?有没有办法获取正在使用的控制器实例,或者对此进行更好的测试?

【问题讨论】:

    标签: ruby-on-rails ruby rspec


    【解决方案1】:

    更好的模式是首先不在控制器中内联系统调用。而是创建一个单独的对象,该对象知道如何杀死您的工作进程并从您的控制器中调用它。 service object pattern 通常用于此目的。它使存根/监视/模拟依赖项并确保它在您的应用程序边界处停止变得更加容易。

    它还允许您单独测试对象。测试普通的旧红宝石对象真的很容易。测试控制器不是。

    module WorkerHandler
      def self.kill_all
        system 'sh bin/resque/kill_resque_workers'
      end
    end
    
    # in your test
    expect(WorkerHandler).to receive(:kill_all)
    

    如果您的服务对象方法在类的实例上运行,您可以使用 stub_const 存根新方法,以便它返回模拟/间谍。

    另一个更新颖的解决方案是通过 Rack 中间件进行依赖注入。你只需write a piece of middleware 将你的对象注入envenv 是从中间件堆栈一路向下传递到您的应用程序的状态变量。例如,这就是 Warden 的工作方式。当您对控制器进行 http 调用或使用 before { session.env('foo.bar', baz) } 时,您可以在规范中传递 env。

    【讨论】:

      猜你喜欢
      • 2010-10-06
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-26
      • 2013-08-18
      相关资源
      最近更新 更多