ckreon
ckreon

Reputation: 51

How to convert an Rspec test with stubs to Minitest

I'm trying to convert a test file from Rspec to Minitest, which up to this point has been going well (very simple tests thus far). But I've come across some stubs and I can't get them to function correctly.

Here is the original Rspec test:

it "takes exactly 1 second to run a block that sleeps for 1 second (with stubs)" do
    fake_time = @eleven_am
    Time.stub(:now) { fake_time }
    elapsed_time = measure do
        fake_time += 60  # adds one minute to fake_time
    end
    elapsed_time.should == 60
end

My attempt to convert that to Minitest:

it "takes exactly 1 second to run a block that sleeps for 1 second (with stubs)" do
    fake_time = @eleven_am
    Time.stub(:now, fake_time) do
        elapsed_time = measure { fake_time += 60 }
        elapsed_time.must_equal 60
    end
end

And the method these are testing:

def measure(rep=1, &block)
    start_time = Time.now
    rep.times { block.call }
    Time.now - start_time
end

The problem I'm having is that with Rspec, the stubs update dynamically with the method execution. When fake_time gets changed in the block, Time.now is immediately updated to correspond with that, meaning the final Time.now call is updated in my method, and it returns the appropriate difference (60).

With Minitest, I seem to override the Time.now response successfully, but it doesn't update with execution, so when fake_time gets adjusted, Time.now does not. This causes it to always return 0, as start_time and Time.now remain identical.

This is probably correct behavior for what it is, I'm just not sure how to get what I want out of it.

How do I make the Minitest stub act like the Rspec stub?

Upvotes: 0

Views: 494

Answers (1)

ckreon
ckreon

Reputation: 51

I received an answer from Chris Kottom on Reddit that I will share here.

The solution is to use a lambda:

Time.stub(:now, -> { fake_time }) do
    ...
end

This creates a dynamic stub that updates with your code execution.

If fake_time is a variable instead of a method (e.g. static vs. dynamic), you can represent this via:

Time.stub(:now, fake_time) do
    ...
end

Upvotes: 1

Related Questions