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
3 Réponses :
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 Si vous souhaitez toujours vérifier la requête de retour, peut vouloir essayer: p> old_products code> est la suivante:
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.
# 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
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
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 i>.