Interfaces and Testing

polaris · · 835 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>This has certainly been covered well in lots of talks about Go and their interfaces, but thought I&#39;d share a really good use for them. Pardon the analogies to other languages...</p> <p>In other languages where implementing an interface requires both fulfilling the contract <em>and</em> explicitly marking the type as fulfilling that contract, testing can sometimes become difficult. If you use a third-party dependency, and a type defines 100 methods, in order to mock that collaborator, your mock object has to define all 100 methods, even if you don&#39;t use them. Furthermore (a bit Java specific), if that type doesn&#39;t implement an interface, you must subclass the type you&#39;re trying to mock. If the class is <code>final</code>, then testing becomes very difficult (requiring special tooling to do bytecode modification, etc.)</p> <p>When testing in Go code, in order to mock a third-party collaborator, it&#39;s as simple as defining an interface which defines <em>only</em> the methods your unit under test will call. Furthermore, because classes <em>are</em> interface types simply by virtue of fulfilling the contract, the third-party class can be used as a type of a first-party interface. </p> <p>Suppose you use a third-party dependency that charges credit cards, paypal, bitcoin, whatever. Even if their type has 100 methods, if you only call the <code>charge</code> method, you can simply do something like:</p> <pre><code>// New code type Charger interface { Charge(float64) boolean, error } type MockCharger struct { ChargeAmount float64 } func (mc *MockCharger) Charge(amt float64) boolean, error { mc.ChargeAmount = amt return true, nil } </code></pre> <p>Then the code under test can receive a <code>Charger</code> rather than a <code>PayPalChargeProvider</code> (concrete type). In the real code, you create and configure a <code>PayPalChargeProvider</code>, but when you&#39;re testing your checkout functionality, you provide a <code>MockCharger</code> and just validate that it got charged what you expect.</p> <p>Again, this isn&#39;t a new observation - lots of talks about interfaces briefly mention this, but it&#39;s really powerful to be able to far more simply mock third-party code you don&#39;t control by just making an interface that you do control.</p> <hr/>**评论:**<br/><br/>bestform: <pre><p>This is one of go&#39;s best features for exactly the reasons you describe. I use the described method here for example: <a href="https://github.com/bestform/souparchive/blob/master/fetch/fetch_test.go" rel="nofollow">https://github.com/bestform/souparchive/blob/master/fetch/fetch_test.go</a></p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

835 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传