<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>单元测试 on 菜鸟程序员</title><link>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/</link><description>Recent content in 单元测试 on 菜鸟程序员</description><generator>Hugo</generator><language>zh-cn</language><atom:link href="https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/index.xml" rel="self" type="application/rss+xml"/><item><title>Golang单元测试-wire依赖注入</title><link>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/golang%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E6%A1%86%E6%9E%B6wire%E5%85%A8%E6%94%BB%E7%95%A5/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/golang%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E6%A1%86%E6%9E%B6wire%E5%85%A8%E6%94%BB%E7%95%A5/</guid><description>&lt;h1 id="golang依赖注入框架wire全攻略">Golang依赖注入框架wire全攻略&lt;a class="td-heading-self-link" href="#golang%e4%be%9d%e8%b5%96%e6%b3%a8%e5%85%a5%e6%a1%86%e6%9e%b6wire%e5%85%a8%e6%94%bb%e7%95%a5" aria-label="Heading self-link">&lt;/a>&lt;/h1>
&lt;p>在前一阵介绍单元测试的系列文章中，曾经简单介绍过&lt;a href="https://github.com/google/wire">wire依赖注入框架&lt;/a>。但当时的wire还处于alpha阶段，不过最近wire已经发布了首个beta版，API发生了一些变化，同时也承诺除非万不得已，将不会破坏API的兼容性。在前文中，介绍了一些wire的基本概况，本篇就不再重复，感兴趣的小伙伴们可以回看一下： &lt;a href="https://juejin.im/post/6844903853536575501">搞定Go单元测试（四）—— 依赖注入框架(wire)&lt;/a>。本篇将具体介绍wire的使用方法和一些最佳实践。&lt;/p>
&lt;p>本篇中的代码的完整示例可以在这里找到：&lt;a href="https://github.com/DrmagicE/wire-examples">wire-examples&lt;/a>&lt;/p>
&lt;h1 id="installing">Installing&lt;a class="td-heading-self-link" href="#installing" aria-label="Heading self-link">&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>go get github.com/google/wire/cmd/wire
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="quick-start">Quick Start&lt;a class="td-heading-self-link" href="#quick-start" aria-label="Heading self-link">&lt;/a>&lt;/h1>
&lt;p>我们先通过一个简单的例子，让小伙伴们对&lt;code>wire&lt;/code>有一个直观的认识。下面的例子展示了一个简易&lt;code>wire&lt;/code>依赖注入示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ ls
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>main.go wire.go
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>main.go&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">package&lt;/span> &lt;span style="color:#000">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">import&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">type&lt;/span> &lt;span style="color:#000">Message&lt;/span> &lt;span style="color:#204a87;font-weight:bold">struct&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">msg&lt;/span> &lt;span style="color:#204a87;font-weight:bold">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">type&lt;/span> &lt;span style="color:#000">Greeter&lt;/span> &lt;span style="color:#204a87;font-weight:bold">struct&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">Message&lt;/span> &lt;span style="color:#000">Message&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">type&lt;/span> &lt;span style="color:#000">Event&lt;/span> &lt;span style="color:#204a87;font-weight:bold">struct&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">Greeter&lt;/span> &lt;span style="color:#000">Greeter&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// NewMessage Message的构造函数&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">NewMessage&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">msg&lt;/span> &lt;span style="color:#204a87;font-weight:bold">string&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#000">Message&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">Message&lt;/span>&lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">msg&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span>&lt;span style="color:#000">msg&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// NewGreeter Greeter构造函数&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">NewGreeter&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">m&lt;/span> &lt;span style="color:#000">Message&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#000">Greeter&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">Greeter&lt;/span>&lt;span style="color:#000;font-weight:bold">{&lt;/span>&lt;span style="color:#000">Message&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#000">m&lt;/span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// NewEvent Event构造函数&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">NewEvent&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">g&lt;/span> &lt;span style="color:#000">Greeter&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#000">Event&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">Event&lt;/span>&lt;span style="color:#000;font-weight:bold">{&lt;/span>&lt;span style="color:#000">Greeter&lt;/span>&lt;span style="color:#000;font-weight:bold">:&lt;/span> &lt;span style="color:#000">g&lt;/span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">e&lt;/span> &lt;span style="color:#000">Event&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#000">Start&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">msg&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">e&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Greeter&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Greet&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">fmt&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Println&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">msg&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">g&lt;/span> &lt;span style="color:#000">Greeter&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#000">Greet&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span> &lt;span style="color:#000">Message&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">g&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Message&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// 使用wire前&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">main&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">message&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">NewMessage&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;hello world&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">greeter&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">NewGreeter&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">message&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">event&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">NewEvent&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">greeter&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">event&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Start&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">// 使用wire后
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">func main() {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic"> event := InitializeEvent(&amp;#34;hello_world&amp;#34;)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic"> event.Start()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#8f5902;font-style:italic">}*/&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>wire.go&lt;/p></description></item><item><title>Golang单元测试-简单示例</title><link>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E7%AE%80%E5%8D%95%E7%9A%84%E7%A4%BA%E4%BE%8B/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E7%AE%80%E5%8D%95%E7%9A%84%E7%A4%BA%E4%BE%8B/</guid><description>&lt;p>one.go&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">package&lt;/span> &lt;span style="color:#000">unittest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">AddOne&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">t&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">+&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">MinusOne&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">t&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">-&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">MultiAddOne&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">t&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">MinusOne&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">t&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">AddOne&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">t&lt;/span> &lt;span style="color:#000;font-weight:bold">=&lt;/span> &lt;span style="color:#000">AddOne&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#000">t&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>one_test.go&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">package&lt;/span> &lt;span style="color:#000">unittest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">import&lt;/span> &lt;span style="color:#000;font-weight:bold">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#4e9a06">&amp;#34;testing&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">.&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;github.com/agiledragon/gomonkey&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">.&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;github.com/smartystreets/goconvey/convey&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">TestMultiAddOne&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">*&lt;/span>&lt;span style="color:#000">testing&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">T&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">Convey&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;TestApplyFunc&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#204a87;font-weight:bold">func&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">Convey&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;input and output param&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#204a87;font-weight:bold">func&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">patches&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">ApplyFunc&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">AddOne&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#204a87;font-weight:bold">func&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t1&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">})&lt;/span> &lt;span style="color:#8f5902;font-style:italic">//对函数AddOne打桩&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">defer&lt;/span> &lt;span style="color:#000">patches&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Reset&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">patches&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">ApplyFunc&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">MinusOne&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#204a87;font-weight:bold">func&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t1&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#204a87;font-weight:bold">int32&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">return&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">-&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">})&lt;/span> &lt;span style="color:#8f5902;font-style:italic">//对函数MinusOne打桩&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">result&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">MultiAddOne&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#0000cf;font-weight:bold">2&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#8f5902;font-style:italic">//看好了我调用的是MultiAddOne函数，而MultiAddOne函数内部调用了AddOne和MinusOne。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">So&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">result&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">ShouldEqual&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#0000cf;font-weight:bold">3&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">})&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">})&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Golang单元测试01</title><link>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E6%90%9E%E5%AE%9Ago%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%9501--%E5%9F%BA%E7%A1%80%E5%8E%9F%E7%90%86/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E6%90%9E%E5%AE%9Ago%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%9501--%E5%9F%BA%E7%A1%80%E5%8E%9F%E7%90%86/</guid><description>&lt;h1 id="搞定go单元测试一基础原理">搞定Go单元测试（一）——基础原理&lt;a class="td-heading-self-link" href="#%e6%90%9e%e5%ae%9ago%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95%e4%b8%80%e5%9f%ba%e7%a1%80%e5%8e%9f%e7%90%86" aria-label="Heading self-link">&lt;/a>&lt;/h1>
&lt;p>单元测试是代码质量的保证。本系列文章将一步步由浅入深展示如何在Go中做单元测试。&lt;/p>
&lt;p>Go对单元测试的支持相当友好，标准包中就支持单元测试，在开始本系阅读之前，需要对标准测试包的基本用法有所了解。&lt;/p>
&lt;p>现在，我们从单元测试的基本思想和原理入手，一起来看看如何基于Go提供的标准测试包来进行单元测试。&lt;/p>
&lt;h2 id="单元测试的难点">单元测试的难点&lt;a class="td-heading-self-link" href="#%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95%e7%9a%84%e9%9a%be%e7%82%b9" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;h3 id="1掌握单元测试粒度">1.掌握单元测试粒度&lt;a class="td-heading-self-link" href="#1%e6%8e%8c%e6%8f%a1%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95%e7%b2%92%e5%ba%a6" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>单元测试粒度是让人十分头疼的问题，特别是对于初尝单元测试的程序员。测试粒度做的太细，会耗费大量的开发以及维护时间，每改一个方法，都要改动其对应的测试方法。当发生代码重构的时候那简直就是噩梦（因为你所有的单元测试又都要写一遍了&amp;hellip;）。 如单元测试粒度太粗，一个测试方法测试了n多方法，那么单元测试将显的非常臃肿，脱离了单元测试的本意，容易把单元测试写成&lt;strong>集成测试&lt;/strong>。&lt;/p>
&lt;h3 id="2-破除外部依赖mockstub-技术">2. 破除外部依赖（mock,stub 技术）&lt;a class="td-heading-self-link" href="#2-%e7%a0%b4%e9%99%a4%e5%a4%96%e9%83%a8%e4%be%9d%e8%b5%96mockstub-%e6%8a%80%e6%9c%af" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>单元测试一般不允许有任何外部依赖（文件依赖，网络依赖，数据库依赖等），我们不会在测试代码中去连接数据库，调用api等。这些外部依赖在执行测试的时候需要被模拟(mock/stub)。在测试的时候，我们使用模拟的对象来模拟真实依赖下的各种行为。如何运用mock/stub来模拟系统真实行为算是单元测试道路上的一只拦路虎。别着急，本文会通过示例来展示如何在Go中使用mock/stub来完成单元测试。&lt;/p>
&lt;blockquote>
&lt;p>有的时候模拟是有效的方便的。但我们要提防过度的mock/stub，因为其会导致单元测试主要在测模拟对象而不是实际的系统。&lt;/p>&lt;/blockquote>
&lt;h2 id="costs-and-benefits">Costs and Benefits&lt;a class="td-heading-self-link" href="#costs-and-benefits" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;p>在受益于单元测试的好处的同时，也必然增加了代码量以及维护成本（单元测试代码也是要维护的）。下面这张&lt;strong>成本/价值象限图&lt;/strong>很清晰的阐述了在不同性质的系统中单元测试&lt;strong>成本&lt;/strong>和&lt;strong>价值&lt;/strong>之间的关系。&lt;/p>
&lt;p>&lt;img src="https://www.azhw.com.cn/content/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/Golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E5%9F%BA%E7%A1%80%E5%8E%9F%E7%90%86/%E6%88%90%E6%9C%AC%E4%BB%B7%E5%80%BC%E8%B1%A1%E9%99%90%E5%9B%BE.png" alt="">&lt;/p>
&lt;h3 id="1依赖很少的简单的代码左下">1.依赖很少的简单的代码(左下)&lt;a class="td-heading-self-link" href="#1%e4%be%9d%e8%b5%96%e5%be%88%e5%b0%91%e7%9a%84%e7%ae%80%e5%8d%95%e7%9a%84%e4%bb%a3%e7%a0%81%e5%b7%a6%e4%b8%8b" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>对于外部依赖少，代码又简单的代码。自然其成本和价值都是比较低的。举Go官方库里errors包为例，整个包就两个方法 &lt;code>New()&lt;/code>和 &lt;code>Error()&lt;/code>，没有任何外部依赖，代码也很简单，所以其单元测试起来也是相当方便。&lt;/p>
&lt;h3 id="2-依赖较多但是很简单的代码右下">2. 依赖较多但是很简单的代码（右下）&lt;a class="td-heading-self-link" href="#2-%e4%be%9d%e8%b5%96%e8%be%83%e5%a4%9a%e4%bd%86%e6%98%af%e5%be%88%e7%ae%80%e5%8d%95%e7%9a%84%e4%bb%a3%e7%a0%81%e5%8f%b3%e4%b8%8b" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>依赖一多，mock和stub就必然增多，单元测试的成本也就随之增加。但代码又如此简单（比如上述errors包的例子），这个时候写单元测试的成本已经大于其价值，&lt;strong>还不如不写单元测试&lt;/strong>。&lt;/p>
&lt;h3 id="3-依赖很少的复杂代码-左上">3. 依赖很少的复杂代码 (左上)&lt;a class="td-heading-self-link" href="#3-%e4%be%9d%e8%b5%96%e5%be%88%e5%b0%91%e7%9a%84%e5%a4%8d%e6%9d%82%e4%bb%a3%e7%a0%81-%e5%b7%a6%e4%b8%8a" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>像这一类代码，是最有价值写单元测试的。比如一些独立的复杂算法（银行利息计算，保险费率计算，TCP协议解析等），像这一类代码外部依赖很少，但却很容易出错，如果没有单元测试，几乎不能保证代码质量。&lt;/p>
&lt;h3 id="4依赖很多又很复杂右上">4.依赖很多又很复杂（右上）&lt;a class="td-heading-self-link" href="#4%e4%be%9d%e8%b5%96%e5%be%88%e5%a4%9a%e5%8f%88%e5%be%88%e5%a4%8d%e6%9d%82%e5%8f%b3%e4%b8%8a" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>这种代码显然是单元测试的噩梦。写单元测试吧，代价高昂；不写单元测试吧，风险太高。像这种代码我们尽量在设计上将其分为两部分：1.处理复杂的逻辑部分 2.处理依赖部分 然后1部分进行单元测试&lt;/p>
&lt;blockquote>
&lt;p>原文参考：&lt;a href="http://blog.stevensanderson.com/2009/11/04/selective-unit-testing-costs-and-benefits/">blog.stevensanderson.com/2009/11/04/…&lt;/a>&lt;/p>&lt;/blockquote>
&lt;h2 id="迈出单元测试第一步">迈出单元测试第一步&lt;a class="td-heading-self-link" href="#%e8%bf%88%e5%87%ba%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95%e7%ac%ac%e4%b8%80%e6%ad%a5" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;h3 id="1-识别依赖抽象成接口">1. 识别依赖，抽象成接口&lt;a class="td-heading-self-link" href="#1-%e8%af%86%e5%88%ab%e4%be%9d%e8%b5%96%e6%8a%bd%e8%b1%a1%e6%88%90%e6%8e%a5%e5%8f%a3" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>识别系统中的外部依赖，普遍来说，我们遇到最常见的依赖无非下面几种：&lt;/p>
&lt;ol>
&lt;li>网络依赖——函数执行依赖于网络请求，比如第三方http-api，rpc服务，消息队列等等&lt;/li>
&lt;li>数据库依赖&lt;/li>
&lt;li>I/O依赖（文件）&lt;/li>
&lt;/ol>
&lt;p>当然，还有可能是依赖还未开发完成的功能模块。但是处理方法都是大同小异的——抽象成接口，通过mock和stub进行模拟测试。&lt;/p>
&lt;h3 id="2-明确需要测什么">2. 明确需要测什么&lt;a class="td-heading-self-link" href="#2-%e6%98%8e%e7%a1%ae%e9%9c%80%e8%a6%81%e6%b5%8b%e4%bb%80%e4%b9%88" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>当我们开始敲产品代码的时候，我们必然已经过初步的设计，已经了解系统中的外部依赖以及业务复杂的部分，这些部分是要优先考虑写单元测试的。在写每一个方法/结构体的时候同时思考这个方法/结构体需不需要测试？如何测试？对于什么样的方法/结构体需要测试，什么样的可以不做，除了可以从上面的&lt;strong>成本/价值象限图&lt;/strong>中获得答案外，还可以参考以下关于&lt;strong>单元测试粒度要做多细&lt;/strong>问题的回答：&lt;/p></description></item><item><title>Golang单元测试02</title><link>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E6%90%9E%E5%AE%9Ago%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%9502--mock%E6%A1%86%E6%9E%B6gomock/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E6%90%9E%E5%AE%9Ago%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%9502--mock%E6%A1%86%E6%9E%B6gomock/</guid><description>&lt;h1 id="搞定go单元测试二-mock框架gomock">搞定Go单元测试（二）—— mock框架(gomock)&lt;a class="td-heading-self-link" href="#%e6%90%9e%e5%ae%9ago%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95%e4%ba%8c-mock%e6%a1%86%e6%9e%b6gomock" aria-label="Heading self-link">&lt;/a>&lt;/h1>
&lt;p>通过阅读上一篇文章，相信你对怎么做单元测试已经有了初步的概念，可以着手对现有的项目进行改造并开展测试了。学会了走路，我们尝试跑起来，本篇主要介绍gomock测试框架，让我们的单元测试更加有效率。&lt;/p>
&lt;h2 id="表格驱动测试方法table-driven-tests">表格驱动测试方法(Table Driven Tests)&lt;a class="td-heading-self-link" href="#%e8%a1%a8%e6%a0%bc%e9%a9%b1%e5%8a%a8%e6%b5%8b%e8%af%95%e6%96%b9%e6%b3%95table-driven-tests" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;p>当针对某方法进行单元测试的时候，通常不止写一个测试用例，我们需要测试该方法在多种入参条件下是否都能正常工作，特别是要针对边界值进行测试。通常这个时候表格驱动测试就派上用场了——&lt;strong>当你发现你在写测试方法的时候用上了复制粘贴，这就说明你需要考虑使用表格驱动测试来构建你的测试方法了&lt;/strong>。我们依旧来举个例子：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">TestTime&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">*&lt;/span>&lt;span style="color:#000">testing&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">T&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">testCases&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000;font-weight:bold">[]&lt;/span>&lt;span style="color:#204a87;font-weight:bold">struct&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// 设计我们的测试用例&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">gmt&lt;/span> &lt;span style="color:#204a87;font-weight:bold">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">loc&lt;/span> &lt;span style="color:#204a87;font-weight:bold">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">want&lt;/span> &lt;span style="color:#204a87;font-weight:bold">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;12:31&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;Europe/Zuri&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;13:31&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">},&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// incorrect location name&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;12:31&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;America/New_York&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;7:31&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">},&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// should be 07:31&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;08:08&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;Australia/Sydney&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#4e9a06">&amp;#34;18:08&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">},&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">for&lt;/span> &lt;span style="color:#000">_&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">tc&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">range&lt;/span> &lt;span style="color:#000">testCases&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span> &lt;span style="color:#8f5902;font-style:italic">// 循环执行测试用例&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">loc&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">err&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">time&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">LoadLocation&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">tc&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">loc&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#000">err&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">!=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">nil&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Fatalf&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;could not load location %q&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">tc&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">loc&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">gmt&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">_&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">time&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Parse&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;15:04&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">tc&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">gmt&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#000">got&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">gmt&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">In&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">loc&lt;/span>&lt;span style="color:#000;font-weight:bold">).&lt;/span>&lt;span style="color:#000">Format&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;15:04&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">);&lt;/span> &lt;span style="color:#000">got&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">!=&lt;/span> &lt;span style="color:#000">tc&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">want&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Errorf&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;In(%s, %s) = %s; want %s&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">tc&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">gmt&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">tc&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">loc&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">got&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">tc&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">want&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>表格驱动测试方法让我们的测试方法更加清晰和简练，减少了复制粘贴，并大大提高的测试代码的可读性。&lt;/p>
&lt;blockquote>
&lt;p>还记得上文说单元测试也是需要维护的吗？单元测试也是代码的一部分，也应当被认真对待。记得要用表格驱动测试的方法来组织你的测试用例，同时别忘了像正式代码那样，写上相应的注释。 更多参考： &lt;a href="https://github.com/golang/go/wiki/TableDrivenTests">github.com/golang/go/w…&lt;/a> &lt;a href="https://blog.golang.org/subtests">blog.golang.org/subtests&lt;/a>&lt;/p>&lt;/blockquote>
&lt;h2 id="使用测试框架gomock">使用测试框架——gomock&lt;a class="td-heading-self-link" href="#%e4%bd%bf%e7%94%a8%e6%b5%8b%e8%af%95%e6%a1%86%e6%9e%b6gomock" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;h3 id="what-is-gomock">What is gomock?&lt;a class="td-heading-self-link" href="#what-is-gomock" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>gomock是Google开源的golang测试框架。或者引用官方的话来说：“GoMock is a &lt;strong>mocking framework&lt;/strong> for the Go programming language”。&lt;/p></description></item><item><title>Golang单元测试03</title><link>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E6%90%9E%E5%AE%9Ago%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%9503--%E6%96%AD%E8%A8%80testify/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E6%90%9E%E5%AE%9Ago%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%9503--%E6%96%AD%E8%A8%80testify/</guid><description>&lt;h1 id="搞定go单元测试三-断言testify">搞定Go单元测试（三）—— 断言（testify）&lt;a class="td-heading-self-link" href="#%e6%90%9e%e5%ae%9ago%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95%e4%b8%89-%e6%96%ad%e8%a8%80testify" aria-label="Heading self-link">&lt;/a>&lt;/h1>
&lt;p>在上一篇，介绍了表格驱动测试方法和gomock测试框架，大大提升了测试效率与质量。本篇将介绍在测试中引入断言（assertion），进一步提升测试效率与质量。&lt;/p>
&lt;h2 id="为什么需要断言库">为什么需要断言库&lt;a class="td-heading-self-link" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e9%9c%80%e8%a6%81%e6%96%ad%e8%a8%80%e5%ba%93" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;p>我们先来看看Go标准包中为什么没有断言，官方在FAQ里面回答了这个问题。&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://golang.org/doc/faq#assertions">golang.org/doc/faq#ass…&lt;/a>&lt;/p>&lt;/blockquote>
&lt;p>总体概括一下大意就是：“Go不提供断言，我们知道这会带来一定的不便，其主要目的是为了防止你们这些程序员在错误处理上偷懒。我们知道这是一个争论点，但是我们觉得这样很coooool~~。”所以，我们引入断言库的原因也很明显了：&lt;del>偷懒&lt;/del>，引入断言能为我们提供便利——提高测试效率，增强代码可读性。&lt;/p>
&lt;h2 id="testify">testify&lt;a class="td-heading-self-link" href="#testify" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;p>在断言库的选择上，我们似乎没有过多的选择，从start数和活跃度来看，基本上是&lt;code>testify&lt;/code>一枝独秀。&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://github.com/stretchr/testify">github.com/stretchr/te…&lt;/a>&lt;/p>&lt;/blockquote>
&lt;p>没有对比就没有伤害，先来看看使用&lt;code>testify&lt;/code>之前的测试方法：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">TestSomeFun&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">*&lt;/span>&lt;span style="color:#000">testing&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">T&lt;/span>&lt;span style="color:#000;font-weight:bold">){&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#000">v&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">!=&lt;/span> &lt;span style="color:#000">want&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Fatalf&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;v值错误，期望值：%s，实际值：%s&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">want&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">v&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#000">err&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">!=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">nil&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Fatalf&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;非预期的错误：%s&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">err&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#000">objectA&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">!=&lt;/span> &lt;span style="color:#000">objectB&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#000">objectA&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">field1&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">!=&lt;/span> &lt;span style="color:#000">objectB&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">field1&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// t.Fatalf() field1值错误...bla bla bla&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#000">objectA&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">field2&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">!=&lt;/span> &lt;span style="color:#000">objectB&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">field2&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// t.Fatalf() field2值错误...bla bla bla&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// 遍历object所有值... bla bla bla&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>上述代码充斥着大量&lt;code>if...else..&lt;/code>判断，大段错误信息拼装（真·体力活&amp;hellip;），运气不好碰到结构体判断要得将其遍历一遍——不直观，低效，实在是不fashion。
现在，我们使用 &lt;code>testify&lt;/code>来改造一下上面的测试示例：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">TestSomeFun&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">*&lt;/span>&lt;span style="color:#000">testing&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">T&lt;/span>&lt;span style="color:#000;font-weight:bold">){&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">a&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">assert&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">New&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">t&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">a&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Equal&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">v&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">want&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">a&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Nil&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">err&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span>&lt;span style="color:#4e9a06">&amp;#34;如果你还是想输出自己拼装的错误信息，可以传第三个参数&amp;#34;&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">a&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Equal&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">objectA&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">objectB&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ce5c00;font-weight:bold">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>三行搞定，测试含义一目了然——直观，高效，简短，fashion。&lt;/p>
&lt;h2 id="总结一下">总结一下&lt;a class="td-heading-self-link" href="#%e6%80%bb%e7%bb%93%e4%b8%80%e4%b8%8b" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;p>testify使用简单，提升显著，可谓是用一次就会爱上的懒人神器。在结合表格驱动测试，gomock和testify后，我们已经能写出一手优雅漂亮的单元测试代码了。不过，光测试代码优雅还不够，我们还需要帮&lt;code>main.go&lt;/code>也打扮打扮。在下一篇，也是本系列最后一篇文章中，我们将介绍wire依赖注入框架，帮&lt;code>main.go&lt;/code>减肥瘦身。&lt;/p></description></item><item><title>Golang单元测试04</title><link>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E6%90%9E%E5%AE%9Ago%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%9504--%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E6%A1%86%E6%9E%B6wire/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.azhw.com.cn/%E7%BC%96%E7%A8%8B/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/golang/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/%E6%90%9E%E5%AE%9Ago%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%9504--%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5%E6%A1%86%E6%9E%B6wire/</guid><description>&lt;h1 id="搞定go单元测试四-依赖注入框架wire">搞定Go单元测试（四）—— 依赖注入框架(wire)&lt;a class="td-heading-self-link" href="#%e6%90%9e%e5%ae%9ago%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95%e5%9b%9b-%e4%be%9d%e8%b5%96%e6%b3%a8%e5%85%a5%e6%a1%86%e6%9e%b6wire" aria-label="Heading self-link">&lt;/a>&lt;/h1>
&lt;p>在第一篇文章中提到过，为了让代码可测，需要用依赖注入的方式来构建我们的对象，而通常我们会在&lt;code>main.go&lt;/code>做依赖注入，这就导致&lt;code>main.go&lt;/code>会越来越臃肿。为了让单元测试得以顺利进行，&lt;code>main.go&lt;/code>牺牲了它本应该纤细苗条的身材。太胖的&lt;code>main.go&lt;/code>可不是什么好的信号，本篇将介绍依赖注入框架（wire），致力于帮助&lt;code>main.go&lt;/code>恢复身材。&lt;/p>
&lt;h2 id="臃肿的main">臃肿的main&lt;a class="td-heading-self-link" href="#%e8%87%83%e8%82%bf%e7%9a%84main" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;p>在&lt;code>main.go&lt;/code>中做依赖注入，意味着在初始化代码中我们要管理：&lt;/p>
&lt;ol>
&lt;li>依赖的初始化顺序&lt;/li>
&lt;li>依赖之间的关系&lt;/li>
&lt;/ol>
&lt;p>对于小型项目而言，依赖的数量比较少，初始化代码不会很多，不需要引入依赖注入框架。但对于依赖较多的中大型项目，初始化代码又臭又长，可读性和维护性变的很差，随意感受一下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#204a87;font-weight:bold">func&lt;/span> &lt;span style="color:#000">main&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">config&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">NewConfig&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// db依赖配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">db&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">err&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">ConnectDatabase&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">config&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87;font-weight:bold">if&lt;/span> &lt;span style="color:#000">err&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">!=&lt;/span> &lt;span style="color:#204a87;font-weight:bold">nil&lt;/span> &lt;span style="color:#000;font-weight:bold">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#204a87">panic&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">err&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// PersonRepository 依赖db&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">personRepository&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">NewPersonRepository&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">db&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// PersonService 依赖配置 和 PersonRepository&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">personService&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">NewPersonService&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">config&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">personRepository&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#8f5902;font-style:italic">// NewServer 依赖配置和PersonService&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">server&lt;/span> &lt;span style="color:#ce5c00;font-weight:bold">:=&lt;/span> &lt;span style="color:#000">NewServer&lt;/span>&lt;span style="color:#000;font-weight:bold">(&lt;/span>&lt;span style="color:#000">config&lt;/span>&lt;span style="color:#000;font-weight:bold">,&lt;/span> &lt;span style="color:#000">personService&lt;/span>&lt;span style="color:#000;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#000">server&lt;/span>&lt;span style="color:#000;font-weight:bold">.&lt;/span>&lt;span style="color:#000">Run&lt;/span>&lt;span style="color:#000;font-weight:bold">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#000;font-weight:bold">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>实践表明，修改有大量依赖关系的初始化代码是一项乏味且耗时的工作。这个时候，我们就需要依赖注入框架来帮忙，简化初始化代码。&lt;/p>
&lt;blockquote>
&lt;p>上述代码来自：&lt;a href="https://blog.drewolson.org/dependency-injection-in-go">blog.drewolson.org/dependency-…&lt;/a>&lt;/p>&lt;/blockquote>
&lt;h2 id="使用依赖注入框架wire">使用依赖注入框架——wire&lt;a class="td-heading-self-link" href="#%e4%bd%bf%e7%94%a8%e4%be%9d%e8%b5%96%e6%b3%a8%e5%85%a5%e6%a1%86%e6%9e%b6wire" aria-label="Heading self-link">&lt;/a>&lt;/h2>
&lt;h3 id="what-is-wire">What is wire?&lt;a class="td-heading-self-link" href="#what-is-wire" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>wire是google开源的依赖注入框架。或者引用官方的话来说：“Wire is a code generation tool that &lt;strong>automates connecting components using dependency injection&lt;/strong>”。&lt;/p>
&lt;blockquote>
&lt;p>&lt;a href="https://github.com/google/wire">github.com/google/wire&lt;/a>&lt;/p>&lt;/blockquote>
&lt;h3 id="why-wire">Why wire?&lt;a class="td-heading-self-link" href="#why-wire" aria-label="Heading self-link">&lt;/a>&lt;/h3>
&lt;p>除了wire，Go的依赖注入框架还有Uber的&lt;a href="https://github.com/uber-go/dig">dig&lt;/a>和Facebook的&lt;a href="https://github.com/facebookarchive/inject">inject&lt;/a>，它们都是使用反射机制来实现运行时依赖注入(runtime dependency injection)，而wire则是采用代码生成的方式来达到编译时依赖注入(compile-time dependency injection)。使用反射带来的性能损失倒是其次，更重要的是反射使得代码难以追踪和调试（反射会令Ctrl+左键失效&amp;hellip;）。而wire生成的代码是符合程序员常规使用习惯的代码，十分容易理解和调试。
关于wire的优点，在官方博文上有更详细的的介绍： &lt;a href="https://blog.golang.org/wire">blog.golang.org/wire&lt;/a>&lt;/p></description></item></channel></rss>