TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Speed Up Your Rails Specs

26 点作者 handler大约 11 年前

6 条评论

al2o3cr大约 11 年前
&quot;expect(widget_factory).to have_received(:create).with({name: &#x27;sprocket&#x27;})&quot;<p>Even better:<p>expect(&quot;my_service.rb&quot;, &quot;line X&quot;).to be(&quot;widget_factory.create&quot;)<p>Or yet better, simply:<p>; # realize that testing the exact implementation is bullshit
xentronium大约 11 年前
RE: Developing Decoupled Code<p>Extra complexity cost is insane and probably not worth it. Basically you move all your crazy stubbing and mocking out of test code and into application code. Do not do this unless you really, really need this kind of dependency injection.
评论 #7387689 未加载
jdminhbg大约 11 年前
I like that the &quot;tightly coupled&quot; service class is 3 extremely simple LOC that should probably just be in a controller anyway, which is &quot;fixed&quot; by creating a class with 3X as many methods and at least twice as much logic to follow, plus a spec twice as long as the original class that tests nothing other than the fact that when you call a method with a set of arguments, that method receives that set of arguments.
ryanbrunner大约 11 年前
I have a massive, and probably not entirely proportionate, negative reaction to constructor injection. It&#x27;s in my mind the ultimate example of making your code more complex in service of your tests.<p>An approach that I&#x27;ve used recently (which is similar enough to parameter-style injection, is to use `class_attribute` at the top of a class to call out dependencies and explicitly provide a default value - so that consumers of your class don&#x27;t need to know what exactly a WidgetFactory is supposed to be:<p><pre><code> class Foo class_attribute :some_service self.some_service = SomeService.new end </code></pre> A nice advantage of this approach is that you can provide a different implementation of some_service on an individual instance of a class, which helps restore your code to a sane state when you&#x27;re done with an individual test, like so:<p><pre><code> describe Foo subject(:foo) { Foo.new } before { foo.some_service = double(SomeService).as_null_object } end </code></pre> On top of that, though, I think calling out dependencies really only makes sense when that dependency involves something external to the codebase itself, or is otherwise secondary to the main purpose of the class. So stub out a repository, or a logger to your hearts content - but there&#x27;s little utility in stubbing out Widget in a WidgetBuilder class IMO.
mcmire大约 11 年前
The problem with dependency injection in this manner is that your test code is using a fake class that&#x27;s injected while your production code is using a real class.<p>This is fine if all you want to do is unit test your classes. That&#x27;s beside the point though -- I would posit if you&#x27;re bolting dependency injection onto your interfaces just to make your tests faster, you&#x27;re not doing it right. Instead, bring that dependency injection into the forefront: to the constructor. Yes, this means to make an object, you&#x27;ll have to make another object first, both in your production and test code. But now your interface acts the same way in both places. If this sounds very Java-like, well... maybe Java got it right. (There was an article on the Twitter blog in the early days about this but I can&#x27;t remember where it is now...)<p>Of course, this <i>is</i> going to introduce complexity and now you have to decide whether that complexity is worth it.
joevandyk大约 11 年前
Maybe if ruby didn&#x27;t take so long to load rails code, this sort of complexity wouldn&#x27;t be necessary...