RSpec脚手架控制器,了解给出的默认值

ale*_*enm 1 rspec controllers scaffold

我正在通过一个rspec教程(peepcode教程).我生成了一些脚手架,我希望有人可以帮助解释如何重新编写描述以便为新手阅读更清楚一些.

describe "POST create" do

    describe "with valid params" do
      it "assigns a newly created weather as @weather" do
        Weather.stub(:new).with({'these' => 'params'}) { mock_weather(:save => true) }
        post :create, :weather => {'these' => 'params'}
        assigns(:weather).should be(mock_weather)
      end

end
Run Code Online (Sandbox Code Playgroud)

这行代码是我试图理解的这一行

Weather.stub(:new).with({'these' => 'params'}) { mock_weather(:save => true) }
Run Code Online (Sandbox Code Playgroud)

我从未见过将方法放在括号内.这究竟意味着什么?

{ mock_weather(:save => true) }
Run Code Online (Sandbox Code Playgroud)

zet*_*tic 6

该声明意味着:

存根new在类方法Weather与参数'these'=>'params'并返回表达式的值mock_weather(:save => true)

一种类似的,也许更清晰的方式来写这个:

Weather.stub(:new).with({'these'=>'params'}).and_return(mock_weather(:save => true))

语法{< some code> }创建一个代码块,在调用存根时执行.

这两种形式的返回值.and_return(){}略有不同; 在第一种情况下,确定何时定义存根,在第二种情况下确定何时接收到消息.它们通常可以互换 - 但有时不可以.

编辑

我觉得这个答案误导了嘲笑,值得回应:

至于你关于"如何使它更清晰"的第一个问题,我们可以从不使用模拟开始.当您不能依赖辅助对象的可预测行为时,模拟对象很有用,辅助对象是一个不重要但必须出现在您的测试用例中的对象.模拟对象的典型使用示例是数据库查询,网络使用,文件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
Run Code Online (Sandbox Code Playgroud)

此规范不需要存在数据库,控制器或模型.它所做的只是声明视图需要呈现一个字符串并验证它是否被渲染 - 这就是Rails视图应该关注的全部内容.唯一的依赖是模板文件和实例变量的存在@post,它由assign语句处理.它甚至不关心它是什么@post,只是它回应:author.

您从rails g scaffold获得的生成代码不是最佳的.生成的代码以一种使所有测试都通过的方式生成,为此它使用模拟对象.我不知道为什么他们这样做,我认为更好的默认是失败的测试,所以你实际上需要做一些事情让他们通过.

脚手架的整个想法是通过生成适用于通常用例的代码来节省时间.您不希望生成的测试实际上也能正常工作吗?

当然,通过使用脚手架,您正在围绕BDD/TDD"测试第一"范例进行最终运行,但可能您已经接受了所涉及的权衡,或者您不会首先使用脚手架.

至于"为什么使用模拟对象",它们允许控制器规范与模型和数据库分离.所以,一旦你知道了推理,它就是"最优的".

使用自动生成的模拟文件,您根本不需要执行任何操作,测试将继续永久通过.这是一个坏主意,也是不好的做法.

只要您不破坏主题代码,它们就会通过.因此,他们在回归测试中具有价值,以确保您不会以导致代码不再符合规范的方式引入新代码或重构.

由于必须在模型文件中编写验证规则,并且您没有使用模拟对象,因此可以确保正在进行实际验证.

在Rails控制器规范中,这种耦合实际上是不合需要的.控制器应该尽可能少地了解模型,因此控制器规范只需要定义验证通过(或失败)时会发生什么 - 而脚手架提供的模拟就是这样做的.如果需要测试模型实例是否对给定的参数集有效,请在模型规范中执行此操作.