Rails和RSpec:在不同的命名空间(模块)中测试具有相同名称的控制器

时间:2017-01-04 10:26:29

标签: ruby-on-rails ruby-on-rails-4 rspec ruby-2.2

我有使用RSpec 3.4.0测试的rails 4.1.16 API应用程序,我遇到了在不同模块中测试同名类的测试问题。

结构是:

app/controllers/bar/notifications_controller.rb

class Bar::NotificationsController < ApiController
  ...
end

和不同模块中具有相同名称的控制器:

app/controllers/foo/bar/notifications_controller.rb

module Foo
  class Bar::NotificationsController < ApiController
    ...
  end
end

Foo是一个新模块,尚未进行测试。 添加之后,旧Bar::NotificationsController的所有相应控制器测试都开始失败。

规范文件:

spec/controllers/bar/notifications_controller_spec.rb

require 'spec_helper'

describe Bar::NotificationsController, type: :controller do
  ...
end

该规范文件中的所有测试都失败并出现相同的错误:

RuntimeError:
   @controller is nil: make sure you set it in your test's setup method.

当我更改Foo模块中的控制器名称时,问题不存在:

app/controllers/foo/bar/foo_notifications_controller.rb

module Foo
  class Bar::FooNotificationsController < ApiController
    ...
  end
end

我已经尝试在spec文件require 'bar/notifications_controller'之上添加并使用类名作为字符串describe "Bar::NotificationsController, type: :controller,但它没有解决问题(同样的错误)。

为什么会这样?解决方案是什么?

我想相信有一件小事我还没试过,我不必污染我的代码和带有无意义名称的结构只是为了让规范通过。

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

通常,我会在类定义中包含所有命名空间。类似的东西:

app/controllers/foo/bar/notifications_controller.rb

class Foo::Bar::NotificationsController < ApiController
  ...
end

乍一看,这可能与以下内容相同:

app/controllers/foo/bar/notifications_controller.rb

module Foo
  class Bar::NotificationsController < ApiController
    ...
  end
end

事实上,这些是不同的。不同之处在于Rails如何处理常量的自动加载。我不会在这里详细介绍,因为它是一个较长的主题,并且在网络领域有很好的文章/帖子。

你可以找到关于Rails如何处理自动加载的好文章,如this one(或尝试谷歌搜索rails constant loading

此外,正如文章所述,Ruby常量加载的操作与Rails加载不同。可以找到关于Ruby常量加载的好信息here(或尝试使用Google搜索ruby constant loading)。