如何保持控制器规格及其模拟DRY?

我被告知这是编写它阻止的控制器的正确方法:

describe UsersController do let(:user){ mock_model(User, id: 2, name: "Jimbo", email: 'jimbo@email.com', password: 'passwordhuzzah', password_confirmation: 'passwordhuzzah') } describe 'PATCH #update' do it "should fail in this case" do User.should_receive(:find).with(user.id.to_s).and_return user user.should_receive(:update_attributes).with({ "email" => user.email, "name" => user.name, "password" => user.password, "password_confirmation" => user.password_confirmation }).and_return true patch :update, id: user.id, user: { email: user.email, name: user.name, password: user.password, password_confirmation: user.password_confirmation } flash[:error].should == "could not update user" response.status.should == 200 end end end 

但我很惊讶,因为它对我来说似乎并不干净。 假设我想在这里创建两个“上下文”。 user.update_attributes调用返回false并返回true。 我的意思是简单地复制粘贴两个块并调整一个小参数吗?

 describe UsersController do let(:user){ mock_model(User, id: 2, name: "Jimbo", email: 'jimbo@email.com', password: 'passwordhuzzah', password_confirmation: 'passwordhuzzah') } it "should pass in this case" do User.should_receive(:find).with(user.id.to_s).and_return user user.should_receive(:update_attributes).with({ "email" => user.email, "name" => user.name, "password" => user.password, "password_confirmation" => user.password_confirmation }).and_return true patch :update, id: user.id, user: { email: user.email, name: user.name, password: user.password, password_confirmation: user.password_confirmation } flash[:error].should == "updated user" response.status.should == 302 end it "should fail in this case" do User.should_receive(:find).with(user.id.to_s).and_return user user.should_receive(:update_attributes).with({ "email" => user.email, "name" => user.name, "password" => user.password, "password_confirmation" => user.password_confirmation }).and_return false patch :update, id: user.id, user: { email: user.email, name: user.name, password: user.password, password_confirmation: user.password_confirmation } flash[:error].should == "could not update user" response.status.should == 200 end end end 

我希望rspec允许我编写这种结构:

 describe 'PATCH #update' do before {} context 'when attributes can be updated' do before {} it "should set the flash" do end it "should set the status" do end end context 'when attributes can\'t be updated' do before {} it "should set the status" do end it "should set the flash" do end end end 

注意它为相同的上下文阻塞的倍数,因为它不是一个期望阻止一个好的做法,因为它允许你看到究竟什么不起作用? 你是怎么想用模拟做到的?