How to stub RSpec update action?

时间:2016-10-04 14:45:05

标签: ruby-on-rails rspec

New to RSpec and having trouble stubbing out an update method (needs to be stubbed) and am running into this error. I have tried a bunch of different ways and can't seem to solve it. I tried to include only the necessary code.

/spec/controllers/admin/business_controller_spec.rb:

require 'spec_helper'

RSpec.describe Admin::BusinessesController, type: :controller do
  render_views

  before(:all) do
    @business = build_stubbed(:business)
  end

  describe '#update' do
    before(:each) do
      allow(Business).to receive(:find).and_return(@business)
      @new_name = Faker::Company.name
      @params = { id: @business.id, business: { name: @new_name } }
    end

    it 'updates business name' do
      expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: @business.confirm_flag, phone_primary: @business.phone_primary).and_return(true)
      xhr :patch, :update, id: @business.id, business: { name: @new_name }
      expect(@business.name).to eq(@new_name)
    end
  end
end

/app/controllers/admin/businesses_controller.rb

class Admin::BusinessesController < Admin::BaseAdminController

  def update
    @business.update_attributes(business_params)
  end

  def business_params
    params.require(:business).permit(:name, :active_flag).merge(confirm_flag: true, phone_primary: '')
  end

end

When I run this test I get this error:

Failures:

  1) Admin::BusinessesController#update updates business name
 Failure/Error: @business.update_attributes(business_params)

   #<Business:0x007fc43c4f5738> received :update_attributes with unexpected arguments
     expected: ({:name=>"Fadel, Larson and Hettinger", :confirm_flag=>true, :phone_primary=>"7832900175"})
          got: ({"name"=>"Fadel, Larson and Hettinger", "confirm_flag"=>true, "phone_primary"=>""})
   Diff:
   @@ -1,4 +1,4 @@
   -[{:name=>"Fadel, Larson and Hettinger",
   -  :confirm_flag=>true,
   -  :phone_primary=>"7832900175"}]
   +[{"name"=>"Fadel, Larson and Hettinger",
   +  "confirm_flag"=>true,
   +  "phone_primary"=>""}]

So it looks like the phone_primary is causing the problem and I change my test expectation line to be:

  describe '#update' do
    before(:each) do
      allow(Business).to receive(:find).and_return(@business)
      @new_name = Faker::Company.name
      @params = { id: @business.id, business: { name: @new_name } }
    end

    it 'updates business name' do
      expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: @business.confirm_flag, **phone_primary: ''**).and_return(true)
      xhr :patch, :update, id: @business.id, business: { name: @new_name }
      expect(@business.name).to eq(@new_name)
    end
  end

and i get the failure:

Failures:

  1) Admin::BusinessesController#update updates business name
 Failure/Error: expect(@business.name).to eq(@new_name)

   expected: "Flatley Inc"
        got: "Samara Kuhic"

And now the names aren't matching

2 个答案:

答案 0 :(得分:2)

我最终通过使用分配来存储重新加载。我的测试现在正在传递:

 describe '#update' do
   before(:each) do
     allow(Business).to receive(:find).and_return(@business)
     @new_name = Faker::Company.name
   end

   it 'updates business name' do
      expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: true, phone_primary: '').and_return(@business)
      xhr :patch, :update, id: @business.id, business: { name: @new_name }
      expect(assigns(:business)).to eq(@business)
      expect(response.status).to eq(200)
    end
  end

不确定这是否是首选方式,但它是否适合我。在Rails 5

中将不推荐使用assigns

答案 1 :(得分:0)

如果您检查原始代码,请在控制器中输入:

def business_params
  params.require(:business).permit(:name, :active_flag).merge(confirm_flag: true, phone_primary: '')
end

您始终将confirm_flag设置为true,将phone_primary设置为''(空字符串)。在你的测试中你有这个:

expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: @business.confirm_flag, phone_primary: @business.phone_primary).and_return(true)

所以,如果您选中confirm_flag,则将其设置为@business.confirm_flag,在这种情况下实际上是true,并且您在控制器中设置的内容很好,但是问题来自phone_primary@business.phone_primary设置为@business.phone_primary,在这种情况下7832900175expect(@business).to receive(:update_attributes).with(name: @new_name, confirm_flag: @business.confirm_flag, phone_primary: '').and_return(true) ,这就是失败的原因。

因此,要解决此问题,您必须将测试更改为:

permit

或将控制器代码从params更改为phone_primary <?php if(isset($_POST['submit'])) { $txtLastName = $_POST['txtLastName']; $txtidnumber = $_POST['txtidnumber']; $txtMedicalAidNumber = $_POST['txtMedicalAidNumber']; //connect to the database $db = mysql_connect ("server", "username", "password") or die ('I cannot connect to the database because: ' . mysql_error()); $conn = new mysqli($servername, $username, $password, $dbname); // Check connection if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } $mydb = mysql_select_db("mediouqp_login"); if($txtLastName != '' && $txtidnumber != '' && $txtMedicalAidNumber != '') { $sql = "SELECT last_name, id_number, medical_id_number FROM patient WHERE last_name LIKE '%" . $txtLastName . "%' OR id_number LIKE '%" . $txtidnumber ."%'"; } else { $sql = "SELECT last_name FROM patient ORDER BY last_name DESC"; } $result = mysql_query($sql); } if($result) { if(mysql_num_rows($result) > 0) { echo 'Total records found are- '.mysql_num_rows($result); } else { echo "No records found."; } } ?> <!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" href="style2.css"> </head> <body> <ul> <li><a href="search_patient.php">PATIENT DETAILS</a> <li><a href="reports.php">REPORTS</a></li> <li><a href="admin.php">ADMINISTRATOR</a></li> <li><a href="downloads.php">DOWNLOADS</a></li> </ul> <div class="headerTitle"> <h1 id="mainHeader">search patient details</h1> </div> <form action="search_patient.php" method="post" name="frm_search" id="frm_search"> <table> <tr> <td class="Label" id="lname">Last Name </td> <td class="Field"> <input type ="lastname" name ="txtLastName" ></input> <span id="spnLastName"></span> </td> </tr> <tr> <td class="Label" id="lname">ID Number </td> <td class="Field"> <input type ="lastname" name ="txtidnumber" ></input> <span id="spnIdNumber"></span> </td> </tr> <tr> <td class="Label" id="lname">Medical Aid Number </td> <td class="Field"> <input type ="medicalaidnumber" name ="txtMedicalAidNumber" ></input> <span id="spnMedicalaidNumber"></span> </td> </tr> <tr> <td class="Label"> </td> <td> <input type="submit" id="btnSearchPatient" value="Submit"></input> <input type = "button" onClick="window.location='create_patient.php';" value="Create Patient" /></input> </td> </tr> </table> </form> <br/> <br/> <table id="tblpatient" class="Grid"> <tr class="Header"> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td>Last Name</td> <td>ID Number</td> <td>Medical Aid</td> </tr> <?php if($result) { while($row = mysql_fetch_array($result)) { $last_name = $row['last_name']; $id_number = $row['id_number']; $medical_id_number = 0;//$row['medical_id_number']; ?> <tr> <td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td> <td><?php echo $last_name;?></td> <td><?php echo $id_number;?></td> <td><?php echo $medical_id_number;?></td> </tr> <?php } } ?> </table> </body> </html> ,这也可以解决您的错误。