这个问题似乎与this one重复,但接受的答案对我的问题没有帮助。
上下文
由于Rails 5不再支持在控制器测试中直接操作会话(现在继承自ActionDispatch :: IntegrationTest),我将走向模拟和存根的黑暗道路。
我知道这是不好的做法,并且有更好的方法来测试控制器(我确实理解他们转向集成测试)但我不想运行完整的集成测试并在单个测试中调用多个操作只是为了设置一个特定的会话变量。
方案
使用Mocha:
实际上很容易模拟/存根会话变量ActionDispatch::Request::Session.any_instance.stubs(:[]).with(:some_variable).returns("some value")
问题是,Rails在会话中存储很多的东西(只在你的一个视图中的任何地方做session.inspect
)并且隐藏:[]
方法显然会阻止访问他们中的任何一个(所以在测试中session[:some_other_variable]
将不再有效。)
问题
有没有办法在使用特定参数调用时保留/模拟:[]
方法并保留所有其他调用未被触发?
我希望像
这样的东西ActionDispatch::Request::Session.any_instance.stubs(:[]).with(:some_variable).returns("some value")
ActionDispatch::Request::Session.any_instance.stubs(:[]).with(anything).returns(original_value)
但我找不到办法让它完成。
答案 0 :(得分:1)
据我所知,这是 mocha 中没有的功能
https://github.com/freerange/mocha/issues/334
我知道这在 rspec-mock
你这样做的一个hacky方法是将原始会话存储在一个对象中,然后模拟每当控制器接收会话时,它返回另一个模拟对象,在这种情况下,您可以返回一个模拟的velue,或者将调用委托给原始会话
class MySession
def initialize(original)
@original = original
end
def [](key)
if key == :mocked_key
2
else
original[key]
end
end
end
let!(original_session) { controller.send(:session) }
let(:my_session) { MySession.new(original_session) }
before do
controller.stubs(:session) { my_session }
end
猜猜 mocha 也允许你做块模拟,所以你不需要这个类,但你需要调用 original_session
但我看不到干净的方法