Rails: How do I write tests for a ruby module? Rails: How do I write tests for a ruby module? ruby ruby

Rails: How do I write tests for a ruby module?


IMHO, you should be doing functional test coverage that will cover all uses of the module, and then test it in isolation in a unit test:

setup do  @object = Object.new  @object.extend(Greeter)endshould "greet person" do  @object.stubs(:format).returns("Hello {{NAME}}")  assert_equal "Hello World", @object.greet("World")endshould "greet person in pirate" do  @object.stubs(:format).returns("Avast {{NAME}} lad!")  assert_equal "Avast Jim lad!", @object.greet("Jim")end

If your unit tests are good, you should be able to just smoke test the functionality in the modules it is mixed into.

Or…

Write a test helper, that asserts the correct behaviour, then use that against each class it's mixed in. Usage would be as follows:

setup do  @object = FooClass.newendshould_act_as_greeter

If your unit tests are good, this can be a simple smoke test of the expected behavior, checking the right delegates are called etc.


Use inline classes (I am not doing any fancy flexmock or stubba/mocha usage just to show the point)

def test_should_callout_to_foo   m = Class.new do     include ModuleUnderTest     def foo        3     end   end.new   assert_equal 6, m.foo_multiplied_by_two end

Any mocking/stubbing library out there should give you a cleaner way to do this. Also you can use structs:

 instance = Struct.new(:foo).new class<<instance     include ModuleUnderTest end instance.foo = 4

If I have a module that is being used in many places I have a unit test for it which does just that (slide a test object under the module methods and test if the module methods function properly on that object).


What I like to do is create a new host class and mix the module into it, something like this:

describe MyModule do  let(:host_class) { Class.new { include MyModule } }  let(:instance) { host_class.new }  describe '#instance_method' do    it 'does something' do      expect(instance.instance_method).to do_something    end  endend