← Back to Upcase

Testing PORO View Models/Presenters that depend on Rails’ ViewContext

(cross-posted from Ruby Rogues Parley)

I still refer to this article on an alternative to Draper all the time. I’ve finally started moving away from Draper, but one thing I’m grappling with is unit testing my view models. With Draper, I was able to use Capybara to test that the HTML was correct:

    markup = Capybara.string(decorator.icon_tag)
    expect(markup).to have_css("img[alt='Task Icon']")
    expect(markup).to have_css("img[width='70']")
    expect(markup).to have_css("img[src='#{expected_source}']")

I was happy enough to not have true isolation because the tests were cheap to write and haven’t turned out to be brittle.

Passing in ViewContext as a dependency then leads me to stubbing and mocking because it’s difficult to recreate. This rings warning bells about not mocking objects we don’t own.

Here’s an idea of my first pass at it: https://gist.github.com/aaronmcadam/8b243db769a3be33244e

Maybe I should inject FakeViewContext objects with implementations of each method I depend upon, and assert the return value of those methods instead. What do you think?

I think you forgot to add the link for the gist.

Ha, thanks @andyw8, I’d copied this post from somewhere else. I’ve updated the original post.

Interesting. I think my interpretation of a view object is a little different. I wouldn’t normally expect a view model to emit markup. I tend to use them in order to build a simpler object to hand over to the view, to reduce its complexity.

Thanks for your thoughts!

I use them for those reasons too. The reason I have some presenters that output markup is because the complexity was getting too much in the view. But maybe I should move some of this stuff into partials and have some logic there instead. I could then use view specs to test them.

Mocking types you don’t own is really the question I have though.