Sometimes I want my monkeys patching #1

Open
chadoh opened this Issue May 15, 2012 · 2 comments

Projects

None yet

2 participants

@chadoh
chadoh commented May 15, 2012

Hi, @tatey! Thanks for your informative article and this nice gem.

I'm a Minitest n00b (been using Test::Unit & a bit o' RSpec) who's used to Mocha. I'm currently trying to figure out the Minitest-way of doing something that was super easy with Mocha:

Suppose I have this code:

def Space
  # ...

  def exists?
    false
  end

  def create
    raise SpaceAlreadyExistsError if self.exists?
    # create space...
  end
end

Now I want to test it like this:

describe Space do
  it "raises SpaceAlreadyExistsError when trying to create a space that already exists" do
    real_space = Space.new
    mock_space = SimpleMock.new real_space
    mock_space.expects :exists?, true
    -> { mock_space.create }.must_raise SpaceAlreadyExistsError
  end
end

This test doesn't work because (I suppose) the SimpleDelegator says "Do I define create? No? Send it to the original object." Then the original object does its thing and never goes up to the level of the SimpleDelegator again.

I can get this test to work with a simple monkey patch, though:

describe Space do
  it "raises SpaceAlreadyExistsError when trying to create a space that already exists" do
    class Space
      def exists?; true; end
    end
    space = Space.new
    -> { space.create }.must_raise SpaceAlreadyExistsError
  end
end

So two questions: Is there a way to do this with SimpleMock and/or Minitest::Mock/SimpleDelegator? And more philosophically, is monkey patching like that bad?

I'd accept that I'm writing code that's too hard to test and that Mocha was enabling me rather than forcing me to think of a simpler way to do things. But I want to see how you'd approach the problem, if that's what you think.

Thanks again for all the work you're doing in this area. I'm happy to be learning from you.

@chadoh
chadoh commented May 15, 2012

Hah. So I figured out why you don't want to just monkey patch the class like that. You probably already know, but for readers who don't: the monkey patch will bleed over into your other tests. So if you need to monkey patch exists? to false in another test, one of them will fail (whichever Minitest runs last).

So my first question remains: is there a way to do this with SimpleMock and/or Minitest::Mock/SimpleDelegator?

Thanks again, @tatey.

@teoulas
teoulas commented Aug 18, 2012

You can simply stub the method:

it "raises error when trying to create an existing space" do
  real_space = Space.new
  real_space.stub(:exists?, true) do
    -> { real_space.create }.must_raise SpaceAlreadyExistsError
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment