Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails RSpec控制器测试_Ruby On Rails_Ruby_Rspec - Fatal编程技术网

Ruby on rails Rails RSpec控制器测试

Ruby on rails Rails RSpec控制器测试,ruby-on-rails,ruby,rspec,Ruby On Rails,Ruby,Rspec,我正在尝试测试订阅是否确实是作为我的公司#create控制器方法的一部分创建的: 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

我正在尝试测试
订阅
是否确实是作为我的
公司#create
控制器方法的一部分创建的:

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
我已经创建了一个测试来验证是否创建了
公司
,它包含在我目前在上面的测试中的4行中

我有一个
公司
工厂,它也创建了一个
订阅

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
而且。。。我有一个
订阅
工厂:

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
这是我的
公司#创建
控制器的方法。。。(是的,它有很多膨胀,一旦我有了一个有效的测试基线,我最终会转移到模型上):

我认为我在正确的轨道上,只是检查一下
订阅是否增加了1
,就像我在我的
公司#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

我做得不对吗?

在您的规范文件
companys\u controller\u 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
controller方法还有一些其他问题超出了您的问题范围。然而,我假设您在处理代码时会发现并解决这些问题。

让我们从低垂的果实开始——您可以简单地将其作为公司的一个虚拟属性,而不是一个“未包装”的黑客TOS

class Company < ApplicationRecord
  validates_acceptance_of :terms # makes a virtual attribute if no column exists
end
您可以将其与
验证相关的
一起使用,以便获得直接反馈。您应该能够通过以下方式进行测试:

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

然而,我不禁想知道,这一逻辑的一部分是否真的应该附加到用户而不是公司——如果您正在跟踪登录设备和位置,那么应该在您的
会话控制器中或用户登录的任何地方进行。

问题是您没有将
术语:“1”
作为请求参数传递到测试。相反,您传递
术语:true
(与“1”不同),并将其放入
公司
属性
散列中。因此,您需要将操作中的条件替换为
if company.save&¶ms[: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

你能在user.save之后调试吗?并运行Subscription.create(…)以查看输出?我可以在测试环境上下文中执行此操作吗?我用的是
guard
。我想你可以用pry remote。否则,只需在“user.save”之后使用byebug在单独的控制台上运行rake测试
bundle exec rake test
->不知道如何构建任务“test”来澄清,您说的是添加
Subscription.create
到当前测试的最后一行?因此,即使是我通过的第一个测试现在也失败了
创建了一个公司
。好的,通过使用
post:create,company:valid_params
使第一个测试通过,解决了这个问题。第二个仍然失败。您需要了解订阅创建(公司id:user.company.id,试用期:true,收费日期:date.today+1.month,每台设备价格:5.00,试用期:date.today+5.days)失败的原因。
行失败。有很多方法可以做到这一点。1) 将其分配给一个变量,并检查它是否实际执行创建操作。2) 用于在代码中放置断点,并运行失败行以查看失败原因。3) 使用日志语句打印subscription.errors。4) 检查例外情况。
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
it "should have a subscription" do
  company = build(:company).attributes
  expect {
    post :create, { company: company, terms: '1' }
  }.to change(Subscription, :count).by(1)
end