2016-04-29 8 views
0

私はRSpecをLeadsコントローラ仕様と書いています。その中で、私はリードコントローラのアクションを作成するためのテストを書いています。今度は私のリードコントローラーがProjectモデルを呼び出して、Contactオブジェクトを作成してプロジェクトに割り当てるオブジェクト(Project)を作成します。私のプロジェクトモデルがContactオブジェクトを作成するかどうかをテストしようとすると、テストは失敗します。私は私の連絡先オブジェクトが作成取得されていない理由を知っていない:(Rspecの2つのオブジェクトの間に関係を確立できません

マイ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

によって変更されたテストは、新しい '連絡先を作成しなかったこと、それは可能です'一致する連絡先が既にデータベースに存在していたか、または検証が失敗したためですか?テストスイートを2回実行する間にデータベースを削除しますか? 'Contact'モデルの検証はありますか? – spickermann

+0

はいspickermann私はContact.rbファイルの最後の2行を見ることができるので、Contactモデルへのバリデーションを持っています。しかし、私が検証を取り除くと、テストは緑色になりますが、とにかく検証が必要です。 – 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 %> 
関連する問題