我有使用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
,但它没有解决问题(同样的错误)。
为什么会这样?解决方案是什么?
我想相信有一件小事我还没试过,我不必污染我的代码和带有无意义名称的结构只是为了让规范通过。
非常感谢您的帮助!
答案 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
)。