在Minitest与Ruby中测试引用其他对象的对象
解决Minitest中模拟对象间引用的问题
嘿,我来帮你搞定这个Minitest的测试问题~ 听起来你是想在测试里搭建两个对象的引用关系,但因为被测对象本身没有:end_place这个属性/方法,只是测试里用这个名称来模拟依赖,导致操作出错对吧?我给你几个针对性的解决方案:
1. 用Stub临时模拟方法返回值(最适配你的场景)
因为你的被测对象本身没有:end_place方法,只是测试需要临时让它返回另一个mock对象,Minitest的stub方法正好能帮你做到这一点——它可以给任意对象临时添加一个方法,仅在代码块内部生效,完全不会影响原对象的结构。
举个例子:
# 实例化你的真实被测对象 trip = Trip.new # 创建需要被返回的mock对象 mock_end_place = Minitest::Mock.new # 可以给mock_end_place设置你需要的行为,比如: mock_end_place.expect(:name, "Paris") # 临时给trip添加:end_place方法,让它返回mock_end_place trip.stub(:end_place, mock_end_place) do # 在这里执行你的测试逻辑,比如调用trip的某个依赖end_place的方法 destination = trip.get_destination # 做断言验证 assert_equal "Paris", destination end # 验证mock的预期是否被触发(如果有的话) mock_end_place.verify
这种方式的好处是完全不需要修改被测对象的代码,只是在测试的局部作用域里临时模拟方法,完美匹配你“被测对象无:end_place属性/方法”的情况。
2. 用Mock构建依赖注入(如果需要验证方法调用)
如果你不仅需要让一个对象返回另一个mock,还想验证:end_place这个方法确实被调用了,那可以用Minitest的Mock来设置预期,并通过依赖注入把mock对象传给被测逻辑:
# 创建两个mock对象 mock_end = Minitest::Mock.new mock_end.expect(:calculate_distance, 500) mock_start = Minitest::Mock.new # 设置mock_start的:end_place方法返回mock_end,同时验证这个方法被调用 mock_start.expect(:end_place, mock_end) # 把mock_start作为依赖传入被测方法 total_distance = RouteCalculator.calculate_total(mock_start) # 验证所有mock的预期都被执行 mock_start.verify mock_end.verify assert_equal 500, total_distance
这种方式适合被测逻辑依赖某个外部对象(比如mock_start),而这个外部对象有:end_place方法的场景——你不需要修改被测对象,只需要把mock作为依赖传进去即可。
3. 常见错误排查
你遇到的错误大概率是这两种情况:
- 误用了Mock来做Stub的事:Mock默认会检查所有调用的方法是否有预设的预期,如果你调用了一个没设置预期的方法(比如
:end_place),就会抛出MockExpectationError。这种情况换成Stub就好。 - Stub的作用域错误:Minitest的
stub方法只有在代码块内部才生效,如果你在代码块外调用end_place,自然会报错说方法不存在。
内容的提问来源于stack exchange,提问作者scumlyfe
相关产品推荐
相关产品推荐

