除了 expect_any_instance_of(#{ControllerClass}).to 接收之外,是否有更好的方法来测试在控制器中调用脚本?
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?
我刚开始使用 RSpec,所以还有很多我不知道的地方。我目前正在研究在按下按钮时应该 运行 脚本的一部分功能。脚本目前是在controller中调用的,不知道有没有好的测试方法
我目前正在使用
expect_any_instance_of(ConfigurationsController)
.to receive(:system)
.with('sh bin/resque/kill_resque_workers')
.and_return(true)
在功能规范中它有效,但 rubocop 抱怨使用 expect_any_instance_of 并且我被告知只有在没有更好的方法时才使用该方法。
有没有更好的方法来测试这个?比如有没有办法获取正在使用的控制器实例,或者对此有更好的测试?
更好的模式是首先不要在控制器中内联系统调用。而是创建一个单独的对象,它知道如何终止您的工作进程并从您的控制器调用它。 service object pattern 通常用于此。它使 stub/spy/mock 依赖项变得更容易,并确保它在您的应用程序边界处停止。
它还可以让您单独测试对象。测试普通的旧 ruby 对象真的很容易。测试控制器不是。
module WorkerHandler
def self.kill_all
system 'sh bin/resque/kill_resque_workers'
end
end
# in your test
expect(WorkerHandler).to receive(:kill_all)
如果您的服务对象方法在 class 的实例上运行,您可以使用 stub_const 来存根新方法,以便它 returns mocks/spies.
另一个更新颖的解决方案是通过 Rack 中间件进行依赖注入。你刚刚write a piece of middleware that injects your object into env。 env
是从中间件堆栈一直传递到您的应用程序的状态变量。例如,这就是 Warden 的工作方式。当您对控制器进行 http 调用或使用 before { session.env('foo.bar', baz) }
.
时,您可以在规范中传递 env
我刚开始使用 RSpec,所以还有很多我不知道的地方。我目前正在研究在按下按钮时应该 运行 脚本的一部分功能。脚本目前是在controller中调用的,不知道有没有好的测试方法
我目前正在使用
expect_any_instance_of(ConfigurationsController)
.to receive(:system)
.with('sh bin/resque/kill_resque_workers')
.and_return(true)
在功能规范中它有效,但 rubocop 抱怨使用 expect_any_instance_of 并且我被告知只有在没有更好的方法时才使用该方法。
有没有更好的方法来测试这个?比如有没有办法获取正在使用的控制器实例,或者对此有更好的测试?
更好的模式是首先不要在控制器中内联系统调用。而是创建一个单独的对象,它知道如何终止您的工作进程并从您的控制器调用它。 service object pattern 通常用于此。它使 stub/spy/mock 依赖项变得更容易,并确保它在您的应用程序边界处停止。
它还可以让您单独测试对象。测试普通的旧 ruby 对象真的很容易。测试控制器不是。
module WorkerHandler
def self.kill_all
system 'sh bin/resque/kill_resque_workers'
end
end
# in your test
expect(WorkerHandler).to receive(:kill_all)
如果您的服务对象方法在 class 的实例上运行,您可以使用 stub_const 来存根新方法,以便它 returns mocks/spies.
另一个更新颖的解决方案是通过 Rack 中间件进行依赖注入。你刚刚write a piece of middleware that injects your object into env。 env
是从中间件堆栈一直传递到您的应用程序的状态变量。例如,这就是 Warden 的工作方式。当您对控制器进行 http 调用或使用 before { session.env('foo.bar', baz) }
.