Search code examples
ruby-on-rails-3unit-testingshoulda

Unit testing a module that is included in ActiveRecord models


I have a module like this (but more complicated):

module Aliasable 
  def self.included(base)
    base.has_many :aliases, :as => :aliasable
  end
end

which I include in several models. Currently for testing I make another module as below, which I just include in the test case

module AliasableTest 
  def self.included(base)
    base.class_exec do 
      should have_many(:aliases)
    end
  end
end

The question is how do I go about testing this module in isolation? Or is the above way good enough. Seems like there is probably a better way to do it.


Solution

  • First off, self.included is not a good way to describe your modules, and class_exec is needlessly complicating things. Instead, you should extend ActiveSupport::Concern, as in:

    module Phoneable
      extend ActiveSupport::Concern
    
      included do
        has_one :phone_number
        validates_uniqueness_of :phone_number
      end
    end
    

    You didn't mention what test framework you're using, but RSpec covers exactly this case. Try this:

    shared_examples_for "a Phoneable" do
      it "should have a phone number" do
        subject.should respond_to :phone_number
      end
    end
    

    Assuming your models look like:

    class Person              class Business
      include Phoneable         include Phoneable
    end                       end
    

    Then, in your tests, you can do:

    describe Person do
      it_behaves_like "a Phoneable"      # reuse Phoneable tests
    
      it "should have a full name" do
        subject.full_name.should == "Bob Smith"
      end
    end
    
    describe Business do
      it_behaves_like "a Phoneable"      # reuse Phoneable tests
    
      it "should have a ten-digit tax ID" do
        subject.tax_id.should == "123-456-7890"
      end
    end