如何在Rails 5.1 + Minitest单元测试中注入Mock对象?
在Rails 5.1 + Minitest中Mock WebSocket连接的解决方案
我来帮你解决这个测试中mock WebSocket连接的问题,核心思路就是拦截WebSocket::Client::Simple.connect这个类方法,让它返回我们预先定义的mock对象,避免实际建立网络连接。下面是具体的实现方案:
1. 构建Mock WebSocket对象
首先创建一个mock实例,模拟你需要的WebSocket行为(比如事件绑定、回调触发等),用Minitest自带的Minitest::Mock就足够了:
mock_websocket = Minitest::Mock.new # 模拟open事件的绑定,并且可以主动触发回调(如果你的connect方法依赖open事件逻辑) mock_websocket.expect :on, nil, [:open] do |event, &block| block.call if event == :open end # 如果你还需要模拟close、message等事件,继续添加expect mock_websocket.expect :on, nil, [:close] mock_websocket.expect :on, nil, [:message]
2. 拦截connect方法并返回Mock
使用Minitest的stub方法,临时替换WebSocket::Client::Simple.connect的行为,在代码块内部这个方法会直接返回我们的mock:
test "connect with open" do # 先创建mock对象 mock_websocket = Minitest::Mock.new mock_websocket.expect :on, nil, [:open] do |event, &block| block.call if event == :open end # 用stub包裹测试逻辑 WebSocket::Client::Simple.stub :connect, mock_websocket do my_worker = my_workers(:one) my_worker.connect # 调用目标方法 # 断言@websocket被正确赋值为mock对象 assert_equal mock_websocket, my_worker.instance_variable_get(:@websocket) # 验证mock上的所有期望都被触发 mock_websocket.verify end end
关键细节说明
- Stub作用域:
stub的效果只在代码块内部生效,出了块之后connect方法会恢复原行为,不会干扰其他测试用例。 - Mock验证:调用
mock_websocket.verify可以确保我们定义的所有expect(比如on(:open))都被实际调用过,保证测试的严谨性。 - 访问实例变量:如果你的
Proxy类没有给@websocket提供公开的访问器(比如attr_reader),可以用instance_variable_get(:@websocket)来检查它的值。
如果你的connect方法还有其他对WebSocket的操作,只需要在mock对象上添加对应的expect即可,比如模拟发送消息的方法:
mock_websocket.expect :send, nil, ["test message"]
内容的提问来源于stack exchange,提问作者satish
相关产品推荐
相关产品推荐

