3
votes

I'm using RSpec for testing. I often find it hard to write good helper specs. Here's an example:

In app/helper/time_helper.rb I have the following code:

# Returns a text field built with given FormBuilder for given attribute                        |  ~                                                                                                    
# (assumed to be a datetime). The field value is a string representation of                    |  ~                                                                                                    
# the datetime with current TimeZone applied.
def datetime_timezone_field(form_builder, attribute)
  date_format = '%Y-%m-%d %H:%M'
  datetime = form_builder.object.send(attribute)
  form_builder.text_field attribute,
                          value: datetime.in_time_zone.strftime(date_format)
end

When testing this, I need to pass a FormBuilder to the method. I know how to create the TestView but how can I create the TestModel used below? In my spec file (spec/helpers/time_helper_spec.rb) I have something like:

describe '#datetime_timezone_field' do
  class TestView < ActionView::Base; end

  let(:form_builder) do
    ActionView::Helpers::FormBuilder.new(TestModel.model_name.singular,
                                         TestModel.new,
                                         TestView.new,
                                         {})
  end

  it # Some tests here to check the output...
end

My problem is TestModel. How do I mock such an object? This helper is not connected to a model in my application. TestModel should be "any model class" in my app. Or are there better ways of writing the helper method to get rid of this problem?

1

1 Answers

1
votes

You're not actually testing the behaviour of the model in anyway, you just need an object that responds to the attribute your passing in.

I'd have thought you could do

class TestModel
  include ActiveModel::Model

  attr_accessor :whatever_attribute
end

You probably don't need all of ActiveModel, but I don't know which parts of it the form builder would expect to have. You can always look these up.

So essentially you'd then do

let(:form_builder) do
    ActionView::Helpers::FormBuilder.new(TestModel.model_name.singular,
                                         TestModel.new(whatever_attribute: Time.zone.now),
                                         TestView.new,
                                         {})
end

I've not tested this but I don't see any reason it shouldn't work.