2

Hi I have a Ruby class with some constant variables using Date:

START_DATE = Date.current.at_beginning_of_month.in_time_zone + 2.days

LAST_DATE = Date.current.at_beginning_of_month.in_time_zone + 10.days

and I have some methods which uses this date inside like below:

Date.current.in_time_zone.between?(START_DATE, LAST_DATE)

in my rspec file I'm using Timecop.freeze and it's breaking my tests.

Is there a workaround to use the same variable for most of my methods? or am I using this incorrectly?

I would appreciate any help!

nrmb
  • 460
  • 1
  • 6
  • 17
  • I wonder how you use these constants in your application? IMHO it doesn't make much sense to store these values in a constant. What happens if you start your server at the end of one month and it runs for a few days? Wouldn't that values then be kind of invalid, because they do not change when a new month starts? Did you consider this issue? How do you fix it? Or don't you care? – spickermann Apr 02 '18 at 09:33
  • hello @spickermann thank you for your inputs, I'm actually quite new in Ruby just a few months using it so I might still be misunderstanding the use of the constant variable. does that mean `Date.current` don't actually get a dynamic variable everyday if the server starts? I made it be constant variable because inside the class there are around 3 methods using these. how do i make it more DRY if not constant variable? – nrmb Apr 02 '18 at 10:29

2 Answers2

1

Whether or not you use Timecop for other interactions in your tests, you may also want to consider stubbing the constants themselves. Once you've tested the logic involved with setting the constants, consider using stub_const to ensure that the constants are set to the values you want in your test suite. For example, you might include a block in your test suite that looks something like this:

before :each do
  stub_const("MyClass::START_DATE", <start_time>)
  stub_const("MyClass::END_DATE", <end_time>)
end

Updated:

Comment below says this doesn't work, which is odd... definitely works for me. Just tested this like this:

class User
  MY_CONST = "foo"

  def my_method
    MY_CONST
  end
end

and then in rspec:

describe User do
  it "works unstubbed" do
    expect(User.new.my_const).to eq("foo")
  end
  it "works stubbed" do
    stub_const("User::MY_CONST", "bar")
    expect(User.new.my_const).to eq("bar")
  end
end
Adam Berman
  • 784
  • 5
  • 16
  • I tried your suggestion @adam but it didn't work. I was using `binding.pry` in rspec and when I tried calling the constant it did have the value of the one in stub_const. but inside my class it still using the current date not from the stub_const – nrmb Apr 02 '18 at 10:25
1

I actually got this answer from the Ruby slack community I got a suggestion to make it a method.

so something like:

def start_date
  Date.current.at_beginning_of_month.in_time_zone + 2.days
end

I also just learned what @spickermann meant with why I shouldn't use constant variable because it will stay constant from the start of the server it will have the initial value. and technically, it's not a constant. :sweatsmile:

nrmb
  • 460
  • 1
  • 6
  • 17