Rails test di db non persistono le modifiche dei record
-
23-09-2019 - |
Domanda
Ho cercato di risolvere un problema per un paio di settimane. Sono in esecuzione test RSpec per il mio Rails app, e stanno bene, tranne per un errore che non posso sembrare ottenere la mia testa intorno lavorando.
- Sto usando MySQL con il motore InnoDB.
- Ho impostato
config.use_transactional_fixtures = true
in spec_helper.rb - carico le mie attrezzature di prova manualmente con il comando
rake spec:db:fixtures:load
. - Il test RSpec è stato scritto per un lavoratore BackgrounDRb, e sta testando che un record può avere il suo stato aggiornato (tramite la gemma state_machine).
Ecco il mio problema:
Ho un modello chiamato Listings
. Il test RSpec chiama il metodo update_sold_items
all'interno di un file chiamato listing_worker.rb
.
Questo metodo chiama listing.sell
per un particolare record, che definisce colonna 'Stato' del record annuncio nei miei 'venduto'.
Finora, questo è tutto funziona bene, ma quando il metodo update_sold_items
finisce, il mio test RSpec fallisce qui:
listing = Listing.find_by_listing_id(listing_id)
listing.state.should == "sold"
expected: "sold",
got: "current" (using ==)
Ho cercato di rintracciare il motivo per cui il cambiamento di stato non è persistente, ma sto praticamente perso. Ecco il risultato di un codice di debug che ho messo nel metodo update_sold_items
durante il test:
pp listing.state # => "current"
listing.sell!
listing.save!
pp listing.state # => "sold"
listing.reload
pp listing.state # => "current"
Non riesco a capire il motivo per cui si salva perfettamente bene, ma poi ritorna al record originale ogni volta che io chiamo reload
o Listing.find
ecc.
Grazie per la lettura di questo, e prego tutte le domande se non ho dato abbastanza informazioni.
Grazie per il vostro aiuto, Nathan B
P.S. Non ho un problema la creazione di nuovi record per le altre classi, e testare i record. Sembra solo per essere un problema quando sto aggiornando i record che già esistono nel database.
Soluzione
Ho il sospetto, come Nathan, problemi di transazione. Prova a mettere un Listing.connection.execute ( "commit") a destra prima della prima salvare chiamare a rompere la transazione e vedere cosa cambia. Che si romperà fuori della transazione in modo tutte le chiamate di rollback supplementari saranno non efficace.
Inoltre, eseguendo un comando "commit", si potrebbe mettere in pausa il test con un debugger e ispezionare il database da un altro client per vedere cosa sta succedendo.
L'altra ipotesi, se la sperimentazione operazione non produce alcun risultato, è che forse il vostro modello in realtà non sta risparmiando al database. Controllare i log delle query. (In particolare trovare la query di aggiornamento).
Questo tipo di problemi davvero puzza! In bocca al lupo!
Altri suggerimenti
Se si vuole indagare su quello che hai in DB durante l'esecuzione di test si potrebbe trovare questo utile ...
Ho un test di rspec dove li risparmio @ user.save e funziona come un fascino, ma poi ho voluto vedere se è davvero salvato nel DB.
Ho aperto console rotaie per ambiente di test
rails c test
Ran
User.all
e come previsto non ha ottenuto nulla
Ho corso la mia spec che contiene:
user_attr_hash = FactoryGirl.attributes_for(:user)
@user = User.new user_attr_hash
@user.save
binding.pry
Ho pensato che fermare il test dopo salvare significherebbe che è persisteva, ma non è questo il caso. Sembra che si impegnano per la connessione viene licenziato dopo (non ho idea di quando: \) Così, come suggerisce @ Tim Harper, si deve sparare che impegnarsi nella console leva:
pry(#<RSpec::Core::ExampleGroup::Nested_1>)> User.connection.execute("COMMIT")
Ora, se si esegue User.all nelle rotaie consolare si dovrebbe vedere;)