[英]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.