-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcontest-rails-testing-monkeypatch.html
56 lines (55 loc) · 7.13 KB
/
contest-rails-testing-monkeypatch.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Using Contest's context() in Rails' controller tests - The Terminal Programmer</title><meta content="2011-06-03T16:16:32-07:00" name="DCTERMS.created" /><meta content="2011-06-03T16:16:32-07:00" name="DCTERMS.modified" /><meta content="Suraj N. Kurapati" name="author" /><meta content="patch, ruby, contest, rails, testing" name="keywords" /><meta content="width=device-width, initial-scale=1" name="viewport" /><meta content="Readably https://github.com/sunaku/readably" name="generator" /><link href="style.css" rel="stylesheet" type="text/css" /><link href="index.atom" rel="alternate" title="feed" type="application/atom+xml" /><script src="js/jquery.slim.min.js"></script></head><body><article data-entry-id="contest-rails-testing-monkeypatch" id="body"><header><div class="navigation"><a class="rootlink" href="index.html#contest-rails-testing-monkeypatch" title="The Terminal Programmer"><span>The Terminal Programmer</span></a></div><h1 class="title">Using Contest's context() in Rails' controller tests</h1><div class="author">Suraj N. Kurapati</div><time class="date" datetime="2011-06-03T16:16:32-07:00"> 3 June 2011</time></header><hr /><div class="description"></div><div class="content"><p><a href="https://web.archive.org/web/20110606112859/http://blog.citrusbyte.com/2009/05/19/introducing-contest/">Contest</a> is a Ruby library that brings <a href="https://github.com/thoughtbot/shoulda#readme">Shoulda</a>-style nestable
contexts, in the form of <code>context()</code> methods, and an easier way to define
test blocks, in the form of <code>should()</code> methods, to Ruby’s <code>Test::Unit</code>
testing framework.</p>
<p>When used inside a <a href="http://rubyonrails.org">Rails</a>’ controller test, Contest’s <code>context()</code>
method <a href="https://github.com/citrusbyte/contest/issues/5">raises the following error</a>:</p>
<div class="highlight"><pre class="highlight plaintext"><code>RuntimeError: @controller is nil: make sure you set it in your test's setup method.
</code></pre></div><p>For example, the following controller test triggers the error:</p>
<div class="highlight"><pre class="highlight ruby"><code><span class="nb">require</span> <span class="s1">'test_helper'</span>
<span class="nb">require</span> <span class="s1">'contest'</span>
<span class="k">class</span> <span class="nc">ExamplesControllerTest</span> <span class="o"><</span> <span class="no">ActionController</span><span class="o">::</span><span class="no">TestCase</span>
<span class="n">context</span> <span class="s2">"index action"</span> <span class="k">do</span>
<span class="n">should</span> <span class="s2">"return a list of examples"</span> <span class="k">do</span>
<span class="n">get</span> <span class="ss">:index</span><span class="p">,</span> <span class="ss">:format</span> <span class="o">=></span> <span class="ss">:json</span>
<span class="n">assert_response</span> <span class="ss">:success</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div><p>This happens because, internally, the <code>context()</code> method creates a new
<code>Test::Unit::TestCase</code>-derived class whose name does not contain that of
the parent controller test (which is <code>ExamplesController</code> in the above
example). As a result, Rails complains when it is unable to automatically
set the <code>@controller</code> instance variable inside the block passed to the
<code>context()</code> method.</p>
<p><a href="https://github.com/citrusbyte/contest/issues/5#issuecomment-677003">Robert Gleeson suggested a workaround</a> where you manually assign the
correct value to the <code>@controller</code> instance variable on behalf of Rails in
the created context’s <code>setup()</code> block:</p>
<div class="highlight"><pre class="highlight ruby"><code><span class="n">context</span> <span class="s2">"index action"</span> <span class="k">do</span>
<span class="n">setup</span> <span class="k">do</span>
<span class="vi">@controller</span> <span class="o">=</span> <span class="no">ExamplesController</span><span class="p">.</span><span class="nf">new</span>
<span class="k">end</span>
<span class="c1"># ...</span>
<span class="k">end</span>
</code></pre></div><p>I automated the application of this workaround through the following
monkeypatch, which you can add directly to your Rails’ test helper file:</p>
<div class="highlight"><pre class="highlight ruby"><code><span class="k">class</span> <span class="nc">ActionController::TestCase</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">context</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span>
<span class="k">super</span> <span class="o">*</span><span class="n">args</span> <span class="k">do</span>
<span class="n">setup</span> <span class="k">do</span>
<span class="c1"># establish the rails controller being tested</span>
<span class="c1"># https://github.com/citrusbyte/contest/issues/5#issuecomment-677003</span>
<span class="nb">ancestors</span> <span class="o">=</span> <span class="nb">self</span><span class="p">.</span><span class="nf">class</span><span class="p">.</span><span class="nf">ancestors</span>
<span class="n">test_case</span> <span class="o">=</span> <span class="nb">ancestors</span><span class="p">[</span><span class="nb">ancestors</span><span class="p">.</span><span class="nf">index</span><span class="p">(</span><span class="no">ActionController</span><span class="o">::</span><span class="no">TestCase</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="vi">@controller</span> <span class="o">=</span> <span class="n">test_case</span><span class="p">.</span><span class="nf">controller_class</span><span class="p">.</span><span class="nf">new</span>
<span class="k">end</span>
<span class="nb">class_eval</span> <span class="o">&</span><span class="n">block</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div><p>And with that, you are now riding the Rails, Contest style! :-)</p>
</div><div class="comments" id="comments"><script>var disqus_container_id = 'comments';
var disqus_title = "Using Contest's context() in Rails' controller tests";
var disqus_url = "https://sunaku.github.io/contest-rails-testing-monkeypatch.html";</script><script async="" src="https://theterminalprogrammer.disqus.com/embed.js"></script></div><hr /><footer><p class="copyright">© 2011 Suraj N. Kurapati</p><p class="credits"><a href="https://github.com/sunaku/readably">Readably</a> written, <a href="https://github.com/sainnhe/everforest">Everforest</a> colored. </p><p>Like my work? 👍 Please <a href="vegan-for-life.html">spare a life</a> today as
thanks! 🐮🐷🐔🐟🙊✌💞</p>
</footer><!--[if lt IE 9]><script src="js/html5shiv.min.js"></script><script src="js/html5shiv-printshiv.min.js"></script><![endif]--><script src="index.js"></script></article></body></html>