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

RSpec脚手架控制器,了解给定的默认值,rspec,controllers,scaffold,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

我正在学习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
这行代码是我想理解的,是这一行吗

Weather.stub(:new).with({'these' => 'params'}) { mock_weather(:save => true) }
我从未见过一种方法被放在大括号内。这究竟意味着什么

{ mock_weather(:save => true) }
该声明意味着:

用参数
'this'=>'params'
在类
Weather
上存根
new
方法,并返回表达式
mock_Weather(:save=>true)

一种类似的、或许更清晰的书写方式是:

Weather.stub(:new).with({'this'=>'params'))and_return(mock_Weather(:save=>true))

语法
{
}
创建一个在调用存根时执行的

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

编辑

我觉得这是对嘲笑的误导,应该得到回应:


关于你的第一个问题“怎么做?” 为了更清楚一点,“我们可以 首先不要使用mock。嘲弄 对象在无法使用时非常有用 依赖于一个可预测的行为 次要对象,是指 不重要,但必须在 您的测试用例。典型的 模拟对象的使用与数据库无关 查询、网络使用、文件i/o。你 不希望你的测试失败,因为 您的计算机失去了网络连接, 或者数据库不可用

诚然,mock可以消除对外部资源的依赖,但这不是它们的唯一目的。mock的真正价值在于,它们允许您为尚不存在的代码编写测试。例如,在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
的响应

从中获得的生成代码 脚手架的轨道不是最优的。 生成的代码是在 使所有测试通过的方式,以及 为此,它使用模拟对象。我不 知道他们为什么这么做,我想 更好的默认设置是测试失败 所以你实际上需要这样做 让他们通过的东西

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

当然,通过使用支架,您正在围绕BDD/TDD“测试优先”范式进行最终运行,但您可能已经接受了所涉及的权衡,否则您将不会首先使用支架

至于“为什么使用模拟对象”,它们允许控制器规范与模型和数据库解耦。因此,是的,一旦你知道了原因,它就是“最优的”

使用自动生成的模拟文件 根本不需要做任何事情 测试将继续通过 永远。这是个坏主意,而且很糟糕 练习

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

既然要写 模型文件中的验证规则, 而且你没有使用模拟对象, 你可以肯定,一个实际的 验证正在进行中

在Rails控制器规范中,这种耦合实际上是不受欢迎的。控制器应该尽可能少地了解模型,因此控制器规范只需要定义验证通过(或失败)时会发生什么——脚手架提供的模拟正好做到了这一点。如果需要测试模型实例是否对给定的一组参数有效,请在模型规范中进行测试。

该语句表示:

用参数
'this'=>'params'
在类
Weather
上存根
new
方法,并返回表达式
mock_Weather(:save=>true)

一种类似的、或许更清晰的书写方式是:

Weather.stub(:new).with({'this'=>'params'))and_return(mock_Weather(:save=>true))

语法
{
}
创建一个在调用存根时执行的

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

编辑

我觉得这是对嘲笑的误导,应该得到回应:


关于你的第一个问题“怎么做?” 为了更清楚一点,“我们可以 首先不要使用mock。嘲弄 对象在无法使用时非常有用 依赖于一个可预测的行为 次要对象,是指 不重要,但必须在 您的测试用例。典型的 模拟对象的使用与数据库无关 查询、网络使用、文件i/o。你 不希望你的测试失败,因为 您的计算机失去了网络连接, 或者数据库不可用

诚然,mock可以消除对外部资源的依赖,但这不是它们唯一的用途
#spec/controllers/weather_controller_spec.rb
describe "POST create" do
  describe "with valid params" do
    it "assigns a newly created weather as @weather" do
      post :create, :weather => {'location' => 'ORD', 'temp'=>'35', 'sample_time'=>'2011-02-04T20:00-0500'}
      assigns(:weather).should be_valid
    end

    it "should redirect you to the weather show page" do
      post :create, :weather => {'location' => 'ORD', 'temp'=>'35', 'sample_time'=>'2011-02-04T20:00-0500'}
      response.should redirect_to(weather_path(assigns[:weather]))
    end
  end

  describe "without valid params" do
    it "should notify that a location is required" do
      post :create, :weather => {'temp'=>'35', 'sample_time'=>'2011-02-04T20:00-0500'}
      flash[:notice].should == 'Location is required.'
      assigns(:weather).should_not be_valid
    end

    it "should notify that a temperature is required" do
      post :create, :weather => {'location' => 'ORD', 'sample_time'=>'2011-02-04T20:00-0500'}
      flash[:notice].should == 'A temperature is required.'
      assigns(:weather).should_not be_valid
    end

    it "should notify that a sample time is required" do
      post :create, :weather => {'location' => 'ORD', 'temp'=>'35'}
      flash[:notice].should == 'A sample time is required.'
      assigns(:weather).should_not be_valid
    end
  end
end
#spec/factories.rb
Factory.define :weather_valid do |f|
  f.location "ORD"
  f.temp "35"
  f.sample_time "2011-02-04T20:00-0500"
end


#spec/controllers/weather_controller_spec.rb
describe "POST create" do
  describe "with valid params" do
    it "assigns a newly created weather as @weather" do
      post :create, :weather => Factory.build(:weather_valid).attributes
      assigns(:weather).should be_valid
    end

    it "should redirect you to the weather show page" do
      post :create, :weather => Factory.build(:weather_valid).attributes
      response.should redirect_to(weather_path(assigns[:weather]))
    end
  end
...