brg
brg

Reputation: 3953

rails model unit test trying to hit database throws nil

Any suggestions on how to resolve this test error. The database has records which I try to fetch during test and run the test against. I am using minitest 5.3.3, rails 4.1.1 app and ruby 2.0.0p247

The test output and error thrown:

 Finished in 0.017919s, 167.4200 runs/s, 55.8067    assertions/s.                                                                                                                                                                                                                                                                                                                                     
  1)       Error:                                                                                                                                                                                     
   Ff::BendRateTest#test_class_method:                                                                                                                                                        
   NoMethodError: undefined method `rate' for nil:NilClass 

Which is caused by this line that uses activerecord scopes to query the database. So I try to get the record nd then get the value of the rate from the fetched record:

d = Ff::BendRate.by_counter(letter_b)

The test class:

 module Ff
   class BendRateTest < ActiveSupport::TestCase

     def test_class_method
       m = Ff::BendRate.convert('2014-05-06', 10, 'us', 'gb')
       assert_equal 5, m
     end  
    end
  end

The model is shown below:

 module Ff
  class BendRate < ActiveRecord::Base
    scope :by_counter, -> (letter) {where(letter: letter) } 

    def self.convert(date, amount, letter_a, letter_b)
     Bender.new(date, letter_a, letter_b).converter(amount)
    end  

  end
 end

The Bender class that we instantiate in the model above:

  class Bender

   def initialize(date = Date.today, letter_a, letter_b)
     @letter_a =  letter_a
     @letter_b = letter_b
     @date = date
   end

   def attempter
    baseup(@letter_a, @date)
    counterup(@letter_b, @date)
   end

   def converter(amount = 10)
    @rate = attempter
    (@rate * amount.to_f).round(4)
   end

   private

   def counterup(letter_b, date)
     d = Ff::BendRate.by_counter(letter_b) 
     e = d.first
     @counteracting = e.rate.to_f
     @counter_up_rate = (@counteracting / @baserater).round(4)
   end

   def baseup (leter_a, date)
    a = Ff::BendRate.by_counter(letter_a) 
    b = a.first
    @baserater = b.rate.to_f
    @base_to_base = ( @baserater / @baserater).round(4)
   end
 end

Upvotes: 0

Views: 91

Answers (1)

Paul Keen
Paul Keen

Reputation: 1420

Your test do not show, why it should return 5 items, you do not have any code which insert manually or by fixtures. You should explicitly show in your tests that you added all needed records, and then check that your methods working correctly with that data.

Elsewhere my steps which I'd use to find the problem:

  1. Write test for BendRate#converter - it should fail with the same error
  2. Write test for Bender#attempter - it should fail with the same error, too
  3. Write tests for scope BendRate.by_counter for two cases letter_a and letter_b - it will fail because you have not setup data

or cheater way:

 def test_class_method
   p Ff::BendRate.all
   m = Ff::BendRate.convert('2014-05-06', 10, 'us', 'gb')
   assert_equal 5, m
 end

Upvotes: 1

Related Questions