tfcmaster9
tfcmaster9

Reputation: 113

ActiveRecord save in after_save callback not persisting during rspec test

I'm working on a foosball logging application.

My models follow the scheme: Game -> Team -> Position -> Goal

In Goal I have an after_save that will check if either team has scored 10 goals. If a team has, then it sets a winner(Team) and sets the Game.completed_at.

This functionality seems to save the winner and Game.completed_at in practice through user testing, but in my Rspec tests after a team reaches 10 goals I see the after_save callback being called in Goal, but after the callback in the test its as if none of those columns were saved. I'm not exactly sure what is going on.

class Goal < ActiveRecord::Base
  after_save :complete_game
    def complete_game

      game = self.position.team.game
      isGameComplete = false

      game.teams.each do |team|
        if team.get_goals_total == 10
            team.winner = true
            team.save!
            puts "complete_game: team.winner: #{team.winner}"

            game.completed_at = DateTime.now
            game.save!

            isGameComplete = true
      end
    end
    puts "complete_game: game.completed_at: #{game.completed_at}"
  end

Rspec Test:

it "sets a winner after ten goals" do 
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create
  @blue_team.positions.first.goals.create

  puts "winner: #{@blue_team.winner}"
  puts "completed_at: '#{@game.completed_at}'"

  expect(@blue_team.winner).to be true
end

Rspec Output:

complete_game: game.completed_at:
complete_game: game.completed_at:
complete_game: game.completed_at:
complete_game: game.completed_at:
complete_game: game.completed_at:
complete_game: game.completed_at:
complete_game: game.completed_at:
complete_game: game.completed_at:
complete_game: game.completed_at:
complete_game: team.winner: true
complete_game: game.completed_at: 02/20/2015 12:44 PM
TEST OUTPUT: winner: false
TEST OUTPUT: completed_at: ''
    sets a winner after ten goals (FAILED - 1)

Looking at the logs the after_save sets the winner/completed_at, but outside of the callback in 'TEST OUTPUT' then winner/completed_at are not set.

Do callbacks in rspec tests not persist changes made in after_save callbacks? Works in production, doesn't seem to save changes in testing.

Upvotes: 0

Views: 1435

Answers (2)

tfcmaster9
tfcmaster9

Reputation: 113

Received the following answer asking the question on reddit.com/r/rails (http://www.reddit.com/r/rails/comments/2wlhrf/how_to_testing_before_save_callbacks/)

After the callback was performed on the Team model, a .reload of the corresponding object was required.

Test passed as expected.

it "sets a winner after ten goals" do

  10.times do
    @blue_team.positions.first.goals.create
  end

  expect(@blue_team.reload.winner).to be true
end

Upvotes: 2

Sharvy Ahmed
Sharvy Ahmed

Reputation: 7405

You need to stub callback actions :

@blue_team.stub(:complete_game).and_return(true)

Upvotes: 0

Related Questions