Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/64.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.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模型属性时出错_Ruby On Rails_Ruby_Rspec_Factory Bot_Shoulda - Fatal编程技术网

Ruby on rails 验证可能依赖于方法的Rails模型属性时出错

Ruby on rails 验证可能依赖于方法的Rails模型属性时出错,ruby-on-rails,ruby,rspec,factory-bot,shoulda,Ruby On Rails,Ruby,Rspec,Factory Bot,Shoulda,我没有很多Rails测试的经验,所以我不完全理解测试框架是如何工作的 我得到的错误是: Failure/Error: self.slug ||= name.parameterize NoMethodError: undefined method `parameterize' for nil:NilClass 即使我使用FactroyGirl(或使用organization.new(…).save的老式方法)创建了一个具有所有属性的新组织,也会发生此错误 我理解错误发生的原因,我不理解name

我没有很多Rails测试的经验,所以我不完全理解测试框架是如何工作的

我得到的错误是:

Failure/Error: self.slug ||= name.parameterize
NoMethodError: 
undefined method `parameterize' for nil:NilClass
即使我使用FactroyGirl(或使用
organization.new(…).save的老式方法)创建了一个具有所有属性的新组织,也会发生此错误

我理解错误发生的原因,我不理解
name
如何被评估为
nil
,因此也不理解如何以正常工作的方式编写测试

我已经使用
puts“short_name:{org.short_name}”
等语句验证了组织及其属性是否存在于测试范围内

组织工厂:

FactoryGirl.define do
  factory :organization, class: Organization do
    name 'Example & Co'

    trait :all_fields do
      slug 'example-co'
      short_name 'Example & Co'
      description ‘This is a description.’
      year_founded 2010
    end
  end
end
以下所有验证测试都适用于其他组织属性。 如果用户未提供slug,则generate_slug方法应该从name属性创建url安全slug。 注意:我不是代码的作者,我只是为一个由承包商构建的应用程序构建了一个测试套件

测试:

第一次测试通过了,我将其包括在内以供参考/验证

RSpec.describe Organization, :type => :model do

  #validating my factory:      
  describe 'FactoryGirl' do
    it 'factory generating all fields should be valid' do
      create(:organization, :all_fields).should be_valid
      build(:organization, :all_fields).should_not be_valid
    end

    it 'factory generating name field should be valid' do
      create(:organization).should be_valid
      build(:organization).should_not be_valid
    end
  end
正在出错的测试:

describe 'name' do
  let(:org) {FactoryGirl.build(:organization, :all_fields)} 
  context 'is valid' do
    # this is the only test on #name that fails
    it { should validate_presence_of(:name) }
  end
end

describe 'slug' do
  let(:org) {FactoryGirl.build(:organization, :all_fields)}
  context 'is valid' do
    # this is the only test on #slug that fails,     
    it { should validate_presence_of(:slug) }
  end
end

describe 'short_name' do
  # All of the tests on short_name fail
  let(:org) {FactoryGirl.build(:organization, :all_fields)}
  context 'is valid' do
    it { should validate_presence_of(:short_name) }
    it { should have_valid(:short_name).when(org.short_name, 'Example & Co') } 
    it { should validate_length_of(:short_name).is_at_most(20) }      
  end

  context 'is not valid' do
    it { should_not have_valid(:short_name).when('a' * 21) }       
  end
end
第一:

您需要在测试中设置正确的主题。这是所有
it
one行程序都将引用的对象。您确实创建了一个
let
,但由于您从未显式地将其设置为subject,因此测试选择了隐式subject(在您的示例中默认为Organization.new)

要设置明确的主题,您可以编写:

describe 'name' do
  subject { FactoryGirl.build(:organization, :all_fields) } 

  it { should validate_presence_of(:name) }
  # or with the new syntax
  it { is_expected.to validate_presence_of(:name) }
end
您可以在此处阅读更多关于隐式与显式主题和一行程序的信息:

第二:

另一个问题是,假设您使用的是
shoulda matchers
gem,它会将
name
设置为
nil
,以查看当属性不存在时,是否会发生验证错误

但是当名称设置为nil时,before_validation回调抛出错误,因为它假定总是查找
name

您可以这样修改回调():

第三:

一个建议。如果你建立了工厂,拥有shoulda matchers gem,你可以编写非常简洁的规范。比如像这样

RSpec.describe Organization, :type => :model do
  # If you fix the callback you don't even need 
  # to set explicit subject here

  it { is_expected.to validate_presence_of(:name) }
  it { is_expected.to validate_lenght_of(:name).is_at_most(255) }
  ... etc

  # Add custom contexts only for the before_validation callbacks,
  # because shoulda-matchers cannot test them.
  # One possible way (there are different ways and opinions on how
  # should implement this kind of test):
  describe '#slug' do
    let(:organization) { described_class.new(name: 'Ab cd', slug: slug) }

    before { organization.valid? }

    subject { organization.slug }

    context 'when it is missing' do
      let(:slug) { nil }
      let(:result) { 'ab_cd' }

      it 'gets created' do
        expect(subject).to eq(result)
      end
    end

    context 'when it is not missing' do
      let(:slug) { 'whatever' }

      it "won't change" do
        expect(subject).to eq(slug)
      end
    end
  end
end
有关更多示例,请先浏览。

您需要在测试中设置正确的主题。这是所有
it
one行程序都将引用的对象。您确实创建了一个
let
,但由于您从未显式地将其设置为subject,因此测试选择了隐式subject(在您的示例中默认为Organization.new)

要设置明确的主题,您可以编写:

describe 'name' do
  subject { FactoryGirl.build(:organization, :all_fields) } 

  it { should validate_presence_of(:name) }
  # or with the new syntax
  it { is_expected.to validate_presence_of(:name) }
end
您可以在此处阅读更多关于隐式与显式主题和一行程序的信息:

第二:

另一个问题是,假设您使用的是
shoulda matchers
gem,它会将
name
设置为
nil
,以查看当属性不存在时,是否会发生验证错误

但是当名称设置为nil时,before_validation回调抛出错误,因为它假定总是查找
name

您可以这样修改回调():

第三:

一个建议。如果你建立了工厂,拥有shoulda matchers gem,你可以编写非常简洁的规范。比如像这样

RSpec.describe Organization, :type => :model do
  # If you fix the callback you don't even need 
  # to set explicit subject here

  it { is_expected.to validate_presence_of(:name) }
  it { is_expected.to validate_lenght_of(:name).is_at_most(255) }
  ... etc

  # Add custom contexts only for the before_validation callbacks,
  # because shoulda-matchers cannot test them.
  # One possible way (there are different ways and opinions on how
  # should implement this kind of test):
  describe '#slug' do
    let(:organization) { described_class.new(name: 'Ab cd', slug: slug) }

    before { organization.valid? }

    subject { organization.slug }

    context 'when it is missing' do
      let(:slug) { nil }
      let(:result) { 'ab_cd' }

      it 'gets created' do
        expect(subject).to eq(result)
      end
    end

    context 'when it is not missing' do
      let(:slug) { 'whatever' }

      it "won't change" do
        expect(subject).to eq(slug)
      end
    end
  end
end

有关更多示例,您可以浏览。

好东西!非常感谢。我喜欢任何能够解释测试框架是如何构造的链接。例如,我在gem文档中看到了对“subject”的引用,但没有解释它是什么或如何使用它。干杯!你能详细说明一下这句话吗:“只为before\u validation回调添加自定义上下文吗?”“?我更新了before_validation回调部分的示例。这是我自己创造类似的东西的方式,但是有不同的方法。(就像测试中的一样…)。希望有帮助!在哪里可以找到更多信息?官方的RSpec文档是一个很好的地方,但是信息有点分散,所以很难形成一个关于如何使用框架的概貌。此外,RSpec在过去几年中经历了很多变化,因此许多较旧的教程在RSpec上可能不再是最新的。除此之外,您还可以对抗许多编写这些规范的风格。Mocking与notmocking、instance变量与let、don/do使用shared_示例等。因此,如果您遇到差异,可能是因为上述原因。有非常好的测试基本Rails应用程序的基本示例。尽管我仍然会批判地看待它。在考虑测试什么或如何测试时,请记住,作为开发人员,您的规范应该为您带来最大的价值(使重构更容易,让您相信一切都将以正确的方式工作,甚至是在关键情况下),并创建对您最有意义的规范。好东西!非常感谢。我喜欢任何能够解释测试框架是如何构造的链接。例如,我在gem文档中看到了对“subject”的引用,但没有解释它是什么或如何使用它。干杯!你能详细说明一下这句话吗:“只为before\u validation回调添加自定义上下文吗?”“?我更新了before_validation回调部分的示例。这是我自己创造类似的东西的方式,但是有不同的方法。(就像测试中的一样…)。希望有帮助!在哪里可以找到更多信息?官方的RSpec文档是一个很好的地方,但是信息有点分散,所以很难形成一个关于如何使用框架的概貌。此外,RSpec在过去几年中经历了很多变化,因此许多较旧的教程在RSpec上可能不再是最新的。除此之外,您还可以对抗许多编写这些规范的风格。模拟与非模拟,实例变量
RSpec.describe Organization, :type => :model do
  # If you fix the callback you don't even need 
  # to set explicit subject here

  it { is_expected.to validate_presence_of(:name) }
  it { is_expected.to validate_lenght_of(:name).is_at_most(255) }
  ... etc

  # Add custom contexts only for the before_validation callbacks,
  # because shoulda-matchers cannot test them.
  # One possible way (there are different ways and opinions on how
  # should implement this kind of test):
  describe '#slug' do
    let(:organization) { described_class.new(name: 'Ab cd', slug: slug) }

    before { organization.valid? }

    subject { organization.slug }

    context 'when it is missing' do
      let(:slug) { nil }
      let(:result) { 'ab_cd' }

      it 'gets created' do
        expect(subject).to eq(result)
      end
    end

    context 'when it is not missing' do
      let(:slug) { 'whatever' }

      it "won't change" do
        expect(subject).to eq(slug)
      end
    end
  end
end