2016-04-29 85 views
0

我在寫一個RSpec,稱爲Leads控制器規範。在這裏,我正在爲主控制器的創建動作寫一個測試。現在,我的引導控制器調用Project model創建一個對象(Project),該對象還創建Contact對象並將其分配給項目。但是當我嘗試測試我的項目模型是否創建聯繫人對象或不是,測試失敗。我不知道爲什麼沒有得到創建我的聯繫對象:(無法在Rspec中的兩個對象之間建立關係

我leads_controller_spec.rb

describe "POST #create" do 
    it "should create a contact too" do 
     my_lead = Fabricate(:project, id: Faker::Number.number(10)) 
     expect{ 
     post :create, project: my_lead.attributes 
     }.to change(Contact, :count).by(1) 
    end 
    it "should be equal to last created contact" do 
     my_lead = Fabricate(:project, id: Faker::Number.number(10)) 
     post :create, project: my_lead.attributes 
     expect(Project.last.contact).to eq(Contact.last) 
    end 
    end 

leads_controller.rb

def create 
    if @lead = Project.add_new_lead(lead_params) 
     @lead.create_activity :create_new_lead, owner: current_user 
     puts "My lead in create action: #{@lead.inspect}" 
    else 
     respond_to do |format| 
     format.html { redirect_to :back, :alert => "Email is already Taken"} 
     end 
    end 
     respond_to do |format| 
     format.html { redirect_to leads_path } 
     end 
    end 

Project.rb

def add_new_lead(inputs, data = {}) 
     if !Contact.where(email: inputs[:email]).present? 
     contact = Contact.create(phone: inputs[:phone], email: inputs[:email], fullname: inputs[:fullname]) 
     project = Project.create(name: inputs[:fullname], flat_status: inputs[:flat_status], flat_type: inputs[:flat_type], flat_area: inputs[:area], location: inputs[:locality], address: inputs[:site_address], customer_type: inputs[:customer_type]) 
     project.contact = contact 
     project.save 

     project 

     else 
     return nil 
     end 
    end 

contact_fabricator.rb

require 'faker' 
Fabricator(:contact) do 
email { "email_#{Kernel.rand(1..30000)}@prestotest.com" } 
fullname "project#{Kernel.rand(1..30000)}" 
address "address#{Kernel.rand(1..30000)}" 

end 

project_fabricator.rb

require 'faker' 
Fabricator(:project) do 

    contact 
end 

contact.rb

field :phone,    type: String   
    field :email,    type: String 
    field :fullname,   type: String 
    field :status,   type: String,  default: "DEFAULT" 
    field :address,    type: String 
    field :new_address,  type: String 
    field :other_data,  type: Hash,   default: {} 

    validates_presence_of :email 
    validates_uniqueness_of :email, :message => "Email already taken" 
+0

失敗消息:預計#COUNT由1變了,但被0 – user191990

+0

變化有沒有可能是你的測試並沒有創造一個新的'聯繫'因爲數據庫中已經存在匹配的聯繫人或驗證失敗?您是否在兩次測試套件之間刪除數據庫?你有聯繫人模式的驗證嗎? – spickermann

+0

是的spickermann我確實有聯繫模式的驗證,你可以看到最後兩行的Contact.rb文件。但是,如果我刪除驗證,那麼測試將變爲綠色,但無論如何我需要驗證。 – user191990

回答

0

您正在使用的工廠錯在你的天賦。您希望使用Fabricate.attributes_for(:project)而不是創建記錄並採用其屬性,因爲這會導致任何唯一性驗證失敗。

require 'rails_helper' 
describe ProjectsContoller 

    describe "POST #create" do 

    # don't forget to test with invalid input! 
    context "with invalid attributes" do 
     let(:attributes) { { foo: 'bar' } } 
     it "does not create a project" do 
     expect do 
      post :create, attributes 
     end.to_not change(Project, :count) 
     end 
    end 

    context "with valid attributes" do 
     let(:attributes) { Fabricate.attributes_for(:project) } 
     it "creates a project" do 
     expect do 
      post :create, attributes 
     end.to change(Project, :count).by(+1) 
     end 
    end 
    end 
end 

當涉及到你的控制器的其餘部分,你應該很可能是使用nested attributes,而不是因爲你不處理,其中接觸的驗證失敗的情況。當您應該使用Contact.new時,您也正在使用Contact.create

請注意,這是一個非常高級的主題,您可能需要先學習基礎知識,稍後再重新討論。

class Project < ActiveRecord::Base 
    belongs_to :contact 
    accepts_nested_attributes_for :contact 
    validates_associated :contact 
end 

class Contact < ActiveRecord::Base 
    has_many :projects 
end 

class ProjectsController < ApplicationController 
    def new 
    @project = Project.new 
    end 

    def create 
    @project = Project.new(project_params) 

    if @project.save 
     format.html { render :new } # don't redirect! 
    else 
     format.html { redirect_to leads_path } 
    end 
    end 

    private 

    def project_params 
     params.require(:project).permit(:foo, :bar, contact_attributes: [:email, :name, :stuff, :more_stuff]) 
    end 
end 

<%= form_for(@project) do |f| %> 

    <%= f.text_field :foo %> 

    # These are the attributes for the contact 
    <%= fields_for :contact do |pf| %> 
    <%= pf.text_field :email %> 
    <% end %> 
<% end %> 
相關問題