Reputation: 51
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
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