Testing methods called on yielded object
I have the following controller test case:
def test_showplain
Cleaner.expect(:parse).with(@somecontent)
Cleaner.any_instance.stubs(:plainversion).returns(@returnvalue)
post :showplain, {:content => @somecontent}
end
This works fine, except that I want the "stubs(:plainversion)" to be an "expects(:plainversion)".
Here's the controller code:
def showplain
Cleaner.parse(params[:content]) do | cleaner |
@output = cleaner.plainversion
end
end
And the Cleaner is simply:
class Cleaner
### other code and methods ###
def self.parse(@content)
cleaner = Cleaner.new(@content)
yiel开发者_JS百科d cleaner
cleaner.close
end
def plainversion
### operate on @content and return ###
end
end
Again, I can't figure out how to reliably test the "cleaner" that is made available from the "parse" method. Any suggestions?
This is a little tricky. The easiest a approach will be to break the problem into two pieces: the testing of the controller and the testing of the controller.
You have the testing of the controller set-- just remove your expectation around plainversion call.
Then, separately, you want to test the Cleaner.parse method.
cleaner = Cleaner.new('x');
cleaner.expects :close
Cleaner.expects(:new).returns(cleaner)
called_with = nil
Cleaner.parse('test') do |p|
called_with = p
end
assert_equal p, cleaner
That is not very clear what's going on. Makes me think that there is a simpler version of this. Can cleaner just be a simple function that takes a string and returns another one? Skip all the yielding and variable scoping? That will be much easier to test.
You might find the documentation for Mocha::Expectation#yields useful.
I've made an attempt at showing how you might do what you want in this gist. Note that I had to tweak the code a bit to get it into a self-contained runnable test.
精彩评论