[mocha-developer] Stubbing ActiveRecord Models gets very difficult with instance methods

John Pywtorak jpywtora at calpoly.edu
Wed Jan 3 16:48:10 EST 2007

Second try with minor correction, doh!

James Mead wrote:
> Stubbing attributes sounds like a bad idea.
> Turning instance methods into class methods for testing sounds like a bad idea.
> We do choose to allow the database trip to determine model attributes.
> In my opinion, it's not worth mocking this out.
> Can you give a concrete example of an instance method you are having
> problems testing? Examples are much easier to discuss without
> ambiguity.

I couldn't agree more.  And, here is an example.

module Fear
    module Models
      class StatsTb < ActiveRecord::Base
        set_table_name "w.stats_tb"

        def check_stat
          h, m = maint_time.split(":").map(&:to_i)
          m_dt = maint_dt.to_time + m.hours + m.minutes
          now = Time.now
          m_dt.day == now.day && now - m_dt > 0

        def self.find_stats
          stats = []
          %w(P_TB P_CURRENT_FLAGS_TB X_TB).each do |tb|
            stats << StatsTb.find_by_table_name(tb, :order => "maint_dt 
desc nulls last", :readonly => true)

This example is not meant to serve as a best solution, or even a good
solution.  It is only for demonstrating difficulty of stubbing for
ActiveRecord model instance methods testing.

So, you can see from the model we have a table with maint_time,
maint_dt, and table_name columns.  StatsTb#check_stat is attempting to
verify a given instance of StatsTb.  So, how would one go about writing
a test for check_stat, specifically using mocha?  Also, attempting to
eliminate all trips to the database, because testing #check_stat does
not need it.  The db connection and all the active record magic are
tested elsewhere right?

So, here was a first attempt example:
require 'test/unit'
require 'date'
require 'fear'
class ModelsTest < Test::Unit::TestCase
    attr :stat

    def setup
      @stat = stub(:table_name => "P_TB", :maint_dt => Date.today, 
:maint_time => "00:00")

    def test_check
      StatsTb.find_stats.each { |st| assert st.check_stat }

So, this does not work, because the blocks st object is not an instance
a real instance with a check method and I can't stub check, because it
is the method under test.

Thanks James for any advice and suggestions.

More information about the mocha-developer mailing list