Search code examples
ruby-on-railsrubyimportmodule

Ruby on Rails: Load Utility Module for Unit Test


I have a module Datetools in lib/utils/datetools.rb:

module Datetools
  def hello
    'world'
  end
end

I'd like to test it with a class called DatetoolsTest in test/utils/datetools_test.rb:

import Datetools

class DatetoolsTest < TestCase
  test 'hello world' do
    assert Datetools.hello() == 'world'
  end
end

When I run:

rails t test/utils/datetools_test.rb

I'm getting the error:

uninitialized constant Datetools (NameError)

How can I get hold of my Datetools module in the test case?

Versions: Ruby 3.3.5, Rails 7.1.4


Solution

  • You seem very confused here.

    lib is not on the autoload paths. So to load it you need to do one of the following:

    • Require the code manually with require Rails.root.join('lib/utils/datetools')
    • Enable autoloading for the lib directory with config.autoload_lib. This is a new feature in Rails 7. In previous versions you would need to manually add the directory to the autoload paths.
    • Put the code in app/utils instead of lib as it and all it's subfolders are autoloading roots.

    However even if you load the code you're still going to get undefined method 'hello' for module Datetools (NoMethodError). If you want the method to be callable as a module method you need to use def self.hello or the module_function method.

    It's also unclear why you're calling import Datetools. What that does is copy the instance methods of Datetools into the recipent which is at that point is main (the Ruby global object).

    If what you actually want to do is to test instance methods of the module then a better way is to create a stand in class in your test:

    class DatetoolsTest < TestCase
      # You could also use Class.new to create an anonymous class instead
      class DummyClass
        import Datetools
      end
    
      test 'hello world' do
        assert_equal DummyClass.new.hello, 'world'
      end
    end
    

    Or import the module into the test class:

    class DatetoolsTest < TestCase
      import Datetools
    
      test 'hello world' do
        assert_equal hello, 'world'
      end
    end