简体   繁体   English

Rspec测试控制器动作创建逻辑

[英]Rspec testing controller action create logic

I'm trying to figure out the logic for testing my controller. 我试图弄清楚测试控制器的逻辑。 As you can see in my controller, if a customer is found by phone number, it should render the customer show page, and if a customer is not found by phone number then it should render the create page. 如您在我的控制器中看到的,如果通过电话号码找到了客户,则应呈现客户显示页面,如果通过电话号码未找到客户,则应呈现创建页面。

I'm using rspec and factorygirl. 我正在使用rspec和factorygirl。

My thought process was to build a test by building a customer, assigning it a specific id: 999999 and phone number. 我的想法是通过建立一个客户并为其分配一个特定的ID:999999和电话号码来构建测试。

Then doing a post: create for a customer by using the same phone number. 然后进行发布:使用相同的电话号码为客户创建。 That should have the response return as customers/id. 那应该将响应返回为客户/ id。

While my code passes the tests, when I change the post: create customer phone number, it still passes. 当我的代码通过测试时,当我更改帖子时:创建客户电话号码,它仍然通过。 I don't know what I'm doing wrong, but that it doesn't seem right. 我不知道我在做什么错,但是这似乎不正确。

Controller: 控制器:

def create        
   if @customer = Customer.find_by(phone: customer_params[:phone])
     redirect_to @customer
   else
     @customer = Customer.new(customer_params)
     if @customer.save
       redirect_to @customer, notice: "Customer was successfully saved"
     else
       render 'new', notice: "Customer was unsuccessfully saved"
     end
   end
 end

Controller Specs #1 (passing): 控制器规格1(通过):

it "redirects to the #show/id path if it is an existing customer" do
   customer = build(:customer)
   customer[:id] = 999999
   customer[:phone] = "999"

   post :create, customer: attributes_for(:customer, phone: "999")            
   expect(response).to redirect_to(:action => :show, :id => assigns(:customer).id)
end

Controller Specs #2 (changed the post: create customer phone) ( passing ): 控制器规格2(更改了职位:创建客户电话)(通过):

it "redirects to the #show/id path if it is an existing customer" do
   customer = build(:customer)
   customer[:id] = 99999
   customer[:phone] = "999"

   post :create, customer: attributes_for(:customer, phone: "939")
   expect(response).to redirect_to(:action => :show, :id => assigns(:customer).id)
end

In both cases, when a customer is found or a new customer is created, the response will be a redirect_to and this is why your tests are passing. 在这两种情况下,当找到一个客户或创建一个新客户时, response将是redirect_to ,这就是测试通过的原因。 Note that since you are using build in your test, this is not saving the customer in the database and therefore your test is always creating a new customer and Customer.find_by(phone: customer_params[:phone]) is always evaluating to nil . 请注意,由于您在测试中使用build ,因此不会将客户保存在数据库中,因此您的测试始终在创建新customer并且Customer.find_by(phone: customer_params[:phone])始终评估为nil

The best way to test your create action is by comparing the count of Customer instances before and after the request is made. 测试您的create操作的最佳方法是比较发出请求之前和之后的Customer实例的数量。 Here is a how you can improve upon your tests. 这是您可以改进测试的方法。

let(:customer) { FactoryGirl.create(:customer, phone: '999') }

context 'user not found by phone' do
  it 'creates a new customer' do
     expect{
       post :create, customer: attributes_for(:customer, phone: "999")  
     }.to change(Customer, :count).by 1
  end

  it 'redirects to the customer path' do
    post :create, customer: attributes_for(:customer, phone: "999")  

    customer = Customer.last
    expect(response).to redirect_to(customer)

    #this is another differentiator between the case where a customer is 
    #found and when one is created
    expect(flash[:notice).to eq "Customer was successfully saved"
  end
end

context 'user not found by phone' do
  before(:each) do 
    #here we create the customer before each test in this context
    customer
  end

  it 'does not create a new customer' do
     expect{
       post :create, customer: attributes_for(:customer, phone: customer.phone)  
     }.not_to change(Customer, :count)
  end

  it 'redirects to the customer path' do
    post :create, customer: attributes_for(:customer, phone: customer.phone)  

    customer = Customer.last
    expect(response).to redirect_to(customer)

    #this is another differentiator between the case where a customer is 
    #found and when one is created
    expect(flash[:notice).to be_nil
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM