0
votes

Vérification de la clause de la clause dans les tests RSPEC

J'ai une portée nommée dans les rails et j'ai un modèle par nom Produit

describe Product do
  describe "checking scope clauses" do
  subject { Product.old_products }
    its(:where_clauses)   { should eq([
      "tagged_with = 'old'"
    ]) }
  end
  end
end


1 commentaires

Sauf si vous développez du code sur lequel le SQL généré doit vraiment être testé, vous ne devriez pas tester l'enregistrement actif brut SQL génère pour vous. Ce serait facile pour vous si vous suivez le comportement du test , pas la mise en œuvre de la stratégie .


3 Réponses :


3
votes

Personnellement, je ne pense pas que la vérification soit retournée SQL d'une portée suffit. La façon dont je vais tester old_products est la suivante: xxx

Si vous souhaitez toujours vérifier la requête de retour, peut vouloir essayer: xxx < / pré>


2 commentaires

Ya c'est vrai mais comment faites-vous le processus ci-dessus?


Oui Ne testez pas le SQL généré, car vous ne contrôlez pas cela (et ce n'est pas votre souhait de vérifier / tester comment la requête réelle est formatée). Vérifiez si l'intention du code correspond au résultat. Bien sûr, cela est un peu plus lent (vérifiant la requête générée vs exécutant réellement la requête et comparant les résultats trouvés), mais aussi moins fragile.



0
votes
# This is better, more readable syntax for scope declaration
class Product < ApplicationRecord
  scope :old_products, -> { where(tagged_with: 'old') }
end

# Something like this would work
describe Product do
  context 'scopes' do
    # Set up something that will always be excluded from the scopes
    let!(:product)     { create :product }
    let!(:scoped_list) { create :product, 3, tagged_with: tag }

    shared_examples_for 'returns scoped records' do
      # This should work with shoulda-matchers 
      # (https://github.com/thoughtbot/shoulda-matchers)
      # Could also not use subject and do something like:
      #   expect(
      #     described_class.send(scope_name.to_sym) 
      #   ).to contain_exactly(scoped_list)
      # and declare let(:scope_name) in your describe blocks
      it 'returns scoped products' do
        should contain_exactly(scoped_list)
      end
    end

    describe '.old_products' do
      subject(:old_products) { described_class.old_products }

      let(:tag) { 'old' }

      it_behaves_like 'returns scoped records'
    end

    describe '.other_scope' do
      subject(:other_scope) { described_class.other_scope }

      let(:tag) { 'other_tag' }

      it_behaves_like 'returns scoped records'
    end
  end
end

There is no value in testing the actual SQL -- it's generated by Rails; what you want to test is that your scope is returning the correct objects
I would use context instead of describe when declaring the scopes test block because you're not describing a class or instance method
Use single quotes instead of double quotes unless you are doing string interpolation -- it's more performant
If you're early in the project and each Product only has a single tag, I would also rename the tagged_with column to be tag

0 commentaires

0
votes
describe Product do
  describe "checking scope clauses" do
  subject { Product.old_products }
    expect(subject.values[:where].instance_values['predicates'].to eq(["tagged_with = 'old'"])
  end
end

0 commentaires