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>.