这句话的意思是:
使用参数'these'=>'params' 对类Weather 存根new 方法并返回表达式mock_weather(:save => true) 的值
类似且可能更清晰的写法是:
Weather.stub(:new).with({'these'=>'params'}).and_return(mock_weather(:save => true))
语法{some code>} 创建一个code block,在调用存根时执行。
.and_return()和{}两种形式的返回值略有不同;在第一种情况下,确定何时定义存根,在第二种情况下,确定何时接收到消息。它们通常可以互换——but sometimes not。
编辑
我觉得this answer 对模拟具有误导性,应该得到回应:
关于你的第一个问题是“如何
让它更清楚一点”,我们可以
从不使用模拟开始。一个模拟
当你不能时,对象很有用
取决于一个可预测的行为
次要对象,一个对象是
不重要但必须出现在
你的测试用例。的典型例子
模拟对象的使用是数据库
查询、网络使用情况、文件 i/o。你
不希望您的测试失败,因为
您的计算机失去了网络连接,
或者数据库不可用。
的确,模拟可以消除对外部资源的依赖,但这不是它们的唯一目的。模拟的真正价值在于它们允许您为尚不存在的代码编写测试。例如,在 Rails 中,您可能决定先编写视图规范。
describe "posts/show.html.erb" do
it "displays the author name" do
assign(:post,mock('post',:author=>"Mark Twain"))
render
rendered.should contain("written by Mark Twain")
end
end
此规范不要求存在数据库、控制器或模型。它所做的只是断言视图需要渲染一个字符串并验证它是否被渲染——这就是 Rails 视图应该关心的所有内容。唯一的依赖是模板文件的存在和实例变量@post,由assign 语句处理。它甚至不关心@post 是什么,只关心它响应:author。
您从中获得的生成代码
rails g 脚手架不是最佳的。
生成的代码是在一个
使所有测试通过的方式,以及
为此它使用模拟对象。我不
知道他们为什么这样做,我认为
更好的默认设置是测试失败
所以你实际上需要做
让他们通过的东西。
脚手架的整个想法是通过生成适用于通常用例的代码来节省时间。您不希望生成的测试也能正常工作吗?
当然,通过使用脚手架,您是在围绕 BDD/TDD“测试优先”范式进行最终运行,但可能您已经接受了所涉及的权衡,或者您一开始就不会使用脚手架。
至于“为什么使用模拟对象”,它们允许控制器规范与模型和数据库分离。所以是的,一旦你知道了推理,它就是“最佳的”。
使用自动生成的模拟文件,您
根本不需要做任何事情并且
测试将继续通过
永远。这是个坏主意,而且很糟糕
练习。
只要您不破坏主题代码,它们只会通过。因此,它们在回归测试中具有价值,可确保您不会引入新代码或以导致代码不再符合规范的方式进行重构。
既然将不得不写
模型文件中的验证规则,
而且您没有使用模拟对象,
你可以确定一个实际的
验证正在进行中。
这种耦合实际上在 Rails 控制器规范中是不可取的。控制器应该尽可能少地了解模型,因此控制器规范只需要定义验证通过(或失败)时会发生什么——而脚手架提供的模拟正是这样做的。如果您需要测试模型实例对于给定的一组参数是否有效,请在模型规范中进行。