Im stuck on the test in listing 10.15 of Michael Hartls ruby on rails tutorial (http://ruby.railstutorial.org/chapters/user-microposts#code-micropost_dependency_test). My user_spec.rb is as follows
require 'spec_helper'
describe User do
  before { @user = User.new(name: "Example User", email: "[email protected]",password: "foobar", password_confirmation: "foobar") }
  subject { @user }
  it { should respond_to(:name) }
  it { should respond_to(:email) }
  it { should respond_to(:password_digest) }
  it { should respond_to(:password) }
  it { should respond_to(:password_confirmation) }
  it { should respond_to(:remember_token) }
  it { should respond_to(:admin) }
  it { should respond_to(:authenticate) }
  it { should respond_to(:microposts) }
  it { should be_valid }
  it { should_not be_admin }
  describe "with admin attribute set to 'true'" do
    before do
      @user.save!
      @user.toggle!(:admin)
    end
    it { should be_admin }
  end
  describe "when name is not present" do
    before { @user.name = " " }
    it { should_not be_valid }
  end
  describe "when email is not present" do
    before { @user.email = " " }
    it { should_not be_valid }
  end
  describe "when name is too long" do
    before { @user.name = "a" * 51 }
    it { should_not be_valid }
  end
  describe "when email format is invalid" do
    it "should be invalid" do
      addresses = %w[user@foo,com user_at_foo.org example.user@foo. foo@bar_baz.com foo@bar+baz.com]
      addresses.each do |invalid_address|
        @user.email = invalid_address
        @user.should_not be_valid
      end
    end
  end
  describe "when email format is valid" do
    it "should be valid" do
      addresses = %w[[email protected] [email protected] [email protected] [email protected]]
      addresses.each do |valid_address|
        @user.email = valid_address
        @user.should be_valid
      end
    end
  end
  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.email = @user.email.upcase
      user_with_same_email.save
    end
    it { should_not be_valid }
  end
  describe "when password is not present" do
    before { @user.password = @user.password_confirmation = " "}
    it { should_not be_valid }
  end
  describe "when password doesn't match confirmation" do
    before { @user.password_confirmation = "mismatch" }
    it { should_not be_valid }
  end
  describe "when password confirmation is nil" do
    before { @user.password_confirmation = nil }
    it { should_not be_valid }
  end
  describe "return value of authenticate method" do
    before { @user.save }
    let(:found_user) { User.find_by_email(@user.email) }
    describe "with valid password" do
      it { should == found_user.authenticate(@user.password) }
    end
    describe "with invalid password" do
      let(:user_for_invalid_password) { found_user.authenticate("invalid") }
      it { should_not == user_for_invalid_password }
      specify { user_for_invalid_password.should be_false }
    end
  end
  describe "with a password that's too short" do
    before { @user.password = @user.password_confirmation = "a" * 5 }
    it { should be_invalid }
  end
  describe "remember token" do
    before { @user.save }
    its(:remember_token) { should_not be_blank }
  end
  describe "micropost associations" do
    before { @user.save }
    let!(:older_micropost) do
      FactoryGirl.create(:micropost, user:@user, created_at: 1.day.ago)
    end
    let!(:newer_micropost) do
      FactoryGirl.create(:micropost, user:@user, created_at: 1.hour.ago)
    end
    it "should have the right microposts in the right order" do
      @user.microposts.should == [newer_micropost, older_micropost]
    end
    it "should destroy the associated microposts" do
      microposts = @user.microposts.dup
      @user.destroy
      microposts.should_not be_empty
      microposts.each do |micropost|
        Micropost.find_by_id(micropost.id).should be_nil
      end
    end
  end
end
When i run the tests i get the following error :
  1) User micropost associations should destroy the associated microposts
     Failure/Error: Micropost.find_by_id(micropost.id).should be_nil
       expected: nil
            got: #<Micropost id: 2, content: "Lorem ipsum", user_id: nil, created_at: "2012-12-19 09:49:24", updated_at: "2012-12-19 10:49:24">
     # ./spec/models/user_spec.rb:133:in `block (4 levels) in <top (required)>'
     # ./spec/models/user_spec.rb:132:in `each'
     # ./spec/models/user_spec.rb:132:in `block (3 levels) in <top (required)>'
In my user.rb i have added the dependent :destroy as follows, which is required for the test to pass.
has_many :microposts, dependent: :destroy
Why is the test still failing ?
Thank You
2.7 The Rails Test Runner Or we can run a single test file by passing the bin/rails test command the filename containing the test cases. This will run all test methods from the test case. You can also run a particular test method from the test case by providing the -n or --name flag and the test's method name.
The standard way to delete associated data in Rails is to let ActiveRecord handle it via dependent: :destroy . In the following example, when the parent model ( author ) is deleted, all data in the dependent models will get deleted by ActiveRecord as well. There is an indexed foreign key, but no foreign key constraint.
The Tests − They are test applications that produce consistent result and prove that a Rails application does what it is expected to do. Tests are developed concurrently with the actual application. The Assertion − This is a one line of code that evaluates an object (or expression) for expected results.
The currently accepted way to test rails controllers is by sending http requests to your application and writing assertions about the response. Rails has ActionDispatch::IntegrationTest which provides integration tests for Minitest which is the Ruby standard library testing framework.
I would encourage you not to do something like:
expect { @user.destroy }.to change(User, :count).by(-1)
This only tests the any user was deleted, it does not confirm that the correct records were deleted. Instead, I would do something like this
@user.destroy
expect { @user.reload }.to raise_error ActiveRecord::RecordNotFound
This ensures the correct user was deleted.
Consider testing with a more abbreviated expect .. to change test:
it "destroys the associated microposts" do
  expect { @user.destroy }.to change(Micropost, :count).by(-2)
end
Replace the -2 with whatever change value you'd expect. For example, if it deletes 1 Micropost record, then change it to -1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With