2017-01-31 9 views
2

Я пытаюсь проверить, что Subscription действительно был создан как часть моего метода Company#create контроллера:Rails RSpec Controller Test

require 'rails_helper' 

RSpec.describe CompaniesController, :type => :controller do 

    before do 
    user = build(:user, :company => nil) 
    login_with(user) 
    end 

    it "should have a subscription" do 
    company = build(:company).attributes 
    terms_accepted = { terms_accepted: true } 
    @company_params = company.merge(terms_accepted) 
    post :create, { company: @company_params } 
    # I need to expect something here like company.subscription.exists? 
    end 
end 

Я уже создал тест, чтобы проверить наличие company создан, который содержится в 4-х строках, которые у меня есть в вышеприведенном тесте.

У меня есть company завод, который также создает subscription:

FactoryGirl.define do 
    factory :company do 
    name "ACME Test" 
    address_1 "123 Shady Lane." 
    address_2 "Suite 400" 
    city "Testville" 
    state "Somewhere" 
    zip_code "12345" 
    has_payment_plan false 
    stripe_id "cus_34d434343e4e3e3" 
    locked false 
    association :subscription 
    end 
end 

И ... У меня есть subscription завод:

FactoryGirl.define do 
    factory :subscription do 
    company_id 1 
    trial true 
    custom nil 
    convert_date nil 
    per_device_price 3 
    trial_expires 5.days.from_now 
    freemium false 
    end 
end 

А вот мой Company#create метод контроллера ... (да, у него много раздутий, и я в конечном итоге перехожу к модели, когда у меня есть базовая линия тестов, которые работают):

def create 
    company = Company.new(company_params) 
    user = current_user 

    if company.save && params[:terms] == "1" 
     user.company = company 
     accepted = true 
     user.terms_accepted = accepted 
     user.save 
     Subscription.create(company_id: user.company.id, trial: true, charge_date: Date.today + 1.month, per_device_price: 5.00, trial_expires: Date.today + 5.days) 
     device = Device.create(is_registered: true, registered_date: Date.today, company_id: user.company.id, name: user.company.name, is_sent: true, sent_date: Date.today) 
     location = Location.create(company_id: user.company.id, identifier: device.identifier, name: company.name) 
     device.serial_number = device.identifier 
     NewDevice.new_device(user, device).deliver 
     flash[:success] = "Welcome!" 
     redirect_to root_path 
    else 
     flash[:notice] = "You did not accept the terms of service." 
     sign_out(user) 
     redirect_to root_path 
    end 
end 

Я думал, что я на правильном пути, просто проверяя, Subscription was increased by 1, как я сделал с моим Company#create теста, но это возвращение:

Failures: 

    1) CompaniesController should have a subscription 
    Failure/Error: 
     expect { 
     post :create, { company: @company_params } 
     }.to change(Subscription, :count).by(1) 

     expected #count to have changed by 1, but was changed by 0 

я это делаю неправильно?

+0

вы можете отлаживать после user.save? и запустите Subscription.create (...), чтобы увидеть результат? – Gaston

+0

Могу ли я сделать это в контексте тестовой среды? Я использую 'guard'. – Godzilla74

+0

Я думаю, вы могли бы использовать pry-remote. В противном случае просто запустите проверку rake на отдельной консоли с помощью beebug после «user.save» – Gaston

ответ

0

Проблема в том, что вы не проходите terms: '1' в качестве параметра запроса в своем тесте. Вместо этого вы проходите terms: true (это не то же самое, что и «1»), а также вы помещаете его в хэш-код companyattributes. Поэтому вам нужно либо заменить условие в своем действии на if company.save && params[:terms] == true, либо пройти '1' в своем тесте.

Это должно работать

it "should have a subscription" do 
    company = build(:company).attributes 
    expect { 
    post :create, { company: company, terms: '1' } 
    }.to change(Subscription, :count).by(1) 
end 
0

В файле спецификации companies_controller_spec.rb Я хотел бы сделать что-то вроде этого:

let(:valid_params) { 
    attributes_for(:company).merge(terms_accepted: true) 
} 

context 'POST #create' do 
    it 'creates a company' do 
    expect do 
     post :create, params: { company: valid_params }, session: {} 
    end.to change(Company, :count).by(1) 
    end 

    it 'creates a subscription' do 
    expect do 
     post :create, params: { company: valid_params }, session: {} 
    end.to change(Subscription, :count).by(1) 
    end 
end 

Если второй спецификации выходит из строя, вам нужно определить, почему. Вы не выполняете обработку ошибок для создания подписки, устройства или местоположения.

Кроме того, есть несколько других проблем с вашим контроллером create, который выходит за рамки вашего вопроса. Тем не менее, я полагаю, вы найдете и рассмотрите их при работе с кодом.

+0

Итак, даже первый тест, который у меня прошел, теперь терпит неудачу «создает компанию». – Godzilla74

+0

Хорошо, обошли проблему, используя «post: create, company: valid_params', чтобы сделать первый тестовый проход. 2-й все еще не удается. – Godzilla74

+0

Вам нужно выяснить, почему 'Subscription.create (company_id: user.company.id, trial: true, charge_date: Date.today + 1.month, per_device_price: 5.00, trial_expires: Date.today + 5.days) 'строка не работает. Есть много способов сделать это. 1) назначить его переменной и проверить, что она фактически создает. 2) Используйте [Pry] (http://pryrepl.org/), чтобы поместить контрольную точку в код и запустить строку с ошибкой, чтобы понять, почему она терпит неудачу. 3) Используйте инструкцию регистрации для распечатки подписки. 4) Проверьте исключения. – Midwire

0

Давайте начнем с низко висящих фруктов - вместо «развернутого» взломанного TOS вы можете просто сделать его виртуальным атрибутом компании.

class Company < ApplicationRecord 
    validates_acceptance_of :terms # makes a virtual attribute if no column exists 
end 

Основная болевая точка в этом контроллере, что вы делаете кучу операций после того, как вы сохраните контроллер, который должен действительно быть сделано раньше.

В Rails при сохранении родительской записи также сохраняются дочерние записи. Вы можете использовать это, чтобы упростить логику этого контроллера:

def create 
    company = Company.new(company_params) 
    subscription = company.subscriptions.new(
    trial: true, 
    charge_date: 1.month.from_now, 
    per_device_price: 5.00, 
    trial_expires: 5.days.from_now 
) 
    # ... 

    if company.save 
    # ... 
    else 
    # ... 
    end 
end 

Вы можете использовать это вместе с validates_associated так, что вы получите прямую обратную связь. Вы должны быть в состоянии проверить это потом:

require 'rails_helper' 

RSpec.describe CompaniesController, :type => :controller do 

    before do 
    user = build(:user, :company => nil) 
    login_with(user) 
    end 

    describe "#create" do 
    let(:valid_attributes) { attributes_for(:company, terms: true) } 
    let(:invalid_attributes) { attributes_for(:company, terms: false) } 

    describe "with valid attributes" do 
     it "creates a company" do 
     expect { 
      post :create, { company: valid_attributes } 
     }.to change(Company, :count).by(+1) 
     end 
     it "creates a subscription" do 
     expect { 
      post :create, { company: valid_attributes } 
     }.to change(Subscription, :count).by(+1) 
     expect(Subscription.last.company).to eq Company.last 
     end 
    end 

    describe "with invalid attributes" do 
     it "does not create a company" do 
     expect { 
      post :create, { company: attributes } 
     }.to_not change(Company, :count) 
     end 
     it "does not creates a subscription" do 
     expect { 
      post :create, { company: invalid_attributes } 
     }.to_not change(Subscription, :count) 
     end 
    end 
    end 
end 

Однако я не могу не задаться вопросом, если часть этой логики на самом деле должна быть приложены к пользователю, а не компаниям - если вы отслеживаете вход устройств и местоположениях это должно быть сделано в вашем SessionsController или везде, где пользователь заходит.