如何在RSpec中使用allow方法mock模块下控制器的私有实例方法
RSpec allow方法mock控制器实例方法解决方案
问题原因
你遇到的报错是两个问题共同导致的:
- 方法类型不匹配:
allow(Users::ProfilesController)的写法是用来Mock类方法的,而你定义的send_request_to_update_in_company是控制器的实例方法,不属于类本身,自然找不到对应实现。 - 拼写错误:你代码中定义的私有方法名是
send_request_to_update_in_comapny(company被误写为comapny,字母顺序颠倒),和你测试中调用的方法名不一致,也是触发报错的直接原因之一。
只用allow方法实现Mock的方案
方案1:Mock当前测试的控制器实例(适用控制器测试)
RSpec Rails的控制器测试默认会自动生成当前被测控制器的实例,暴露为controller变量,你直接对这个实例打Mock即可:
首先先修正代码中的方法名拼写错误:
# 修正前 def send_request_to_update_in_comapny(payload) # 修正后 def send_request_to_update_in_company(payload)
然后在测试中修改Mock代码为:
allow(controller).to receive(:send_request_to_update_in_company).and_return({ 'code' => 500 })
方案2:Mock底层依赖(适用所有测试类型,更符合最佳实践)
更推荐的做法是不Mock被测类自身的方法,而是Mock它的外部依赖,测试稳定性更高,也不需要区分实例/类方法:
# 直接Mock CompanyRequestService的返回结果 mock_response = double(body: { 'code' => 500 }.to_json) mock_service = double(call: mock_response) allow(Api::V1::CompanyRequestService).to receive(:new).and_return(mock_service)
补充说明
allow_any_instance_of是对所有该类的实例打Mock,会有额外的性能开销,也可能意外影响其他测试逻辑,直接对当前测试场景的单个实例/依赖打Mock是更安全的写法。
内容的提问来源于stack exchange,提问作者Emmanu
相关产品推荐
相关产品推荐

