Unit testing a module that is included in ActiveRecord models
Asked Answered
S

1

5

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.

Stauder answered 11/7, 2011 at 23:47 Comment(0)
L
7

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
Laughing answered 12/7, 2011 at 0:32 Comment(3)
Thanks, that is super helpful. Do you know of the correct way to do it with Test::Unit (and shoulda)?Stauder
As far as I know, Test::Unit doesn't have a similar facility. Of course, you could always just make a module like PhoneableTests in this example and then reuse it by including that.Laughing
I will mark this as a correct answer and I might ask a different question about shoulda then, or maybe I should just jump on the RSpec band wagon.Stauder

© 2022 - 2024 — McMap. All rights reserved.