首页 > 其他分享 >Go语言精进之路读书笔记第30条——使用接口提高代码的可测试性

Go语言精进之路读书笔记第30条——使用接口提高代码的可测试性

时间:2024-02-20 13:34:26浏览次数:27  
标签:string err 读书笔记 adapter 30 content Go com subject

Go语言有一个惯例是让单元测试代码时刻伴随着你编写的Go代码。

单元测试是自包含和自运行的,运行时一般不会依赖外部资源(如外部数据库、外部邮件服务器等),并具备跨环境的可重复性(既可在开发人员的本地运行,也可以在持续集成的环境中运行)。

30.1 实现一个附加免责声明的电子邮件发送函数

v1版本实现中,由于"github.com/jordan-wright/email"中Email实例的Send方法会真实地连接外部的邮件服务器,因此该测试每执行一次就会向目标电子邮箱发送一封电邮。

如果用例中的参数有误或执行用例的环境无法联网又或无法访问邮件服务器,那么这个测试将会以失败告终,因此这种测试代码并不具备跨环境的可重复性。

归根结底,是v1版本的实现和"github.com/jordan-wright/email"有紧密的依赖,耦合较深。

30.2 使用接口来降低耦合

v2版本的测试用例不再对外部有任何依赖,是具备跨环境可重复性的。v2版本可以验证content字段中是否包含免责声明。

type FakeEmailSender struct {
    subject string
    from    string
    to      []string
    content string
}

func (s *FakeEmailSender) Send(subject, from string,
    to []string, content string, mailserver string, a smtp.Auth) error {
    s.subject = subject
    s.from = from
    s.to = to
    s.content = content
    return nil
}

func TestSendMailWithDisclaimer(t *testing.T) {
    s := &FakeEmailSender{}
    err := mail.SendMailWithDisclaimer(s, "gopher mail test v2",
        "YOUR_MAILBOX",
        []string{"DEST_MAILBOX"},
        "hello, gopher",
        "smtp.163.com:25",
        smtp.PlainAuth("", "YOUR_EMAIL_ACCOUNT", "YOUR_EMAIL_PASSWD!", "smtp.163.com"))
    if err != nil {
        t.Fatalf("want: nil, actual: %s\n", err)
        return
    }

    want := "hello, gopher" + "\n\n" + mail.DISCLAIMER
    if s.content != want {
        t.Fatalf("want: %s, actual: %s\n", want, s.content)
    }
}

如果依然要使用"github.com/jordan-wright/email"中Email实例作为邮件发送者,可以使用一个适配器对该Email实例进行包装,使其成为接口MailSender的实现者。

type EmailSenderAdapter struct {
    e *email.Email
}

func (adapter *EmailSenderAdapter) Send(subject, from string,
    to []string, content string, mailserver string, a smtp.Auth) error {
    adapter.e.Subject = subject
    adapter.e.From = from
    adapter.e.To = to
    adapter.e.Text = []byte(content)
    return adapter.e.Send(mailserver, a)
}

func ExampleSendMailWithDisclaimer() {
    adapter := &EmailSenderAdapter{
        e: email.NewEmail(),
    }
    err := mail.SendMailWithDisclaimer(adapter, "gopher mail test v2",
        "YOUR_MAILBOX",
        []string{"DEST_MAILBOX"},
        "hello, gopher",
        "smtp.163.com:25",
        smtp.PlainAuth("", "YOUR_EMAIL_ACCOUNT", "YOUR_EMAIL_PASSWD!", "smtp.163.com"))
    if err != nil {
        fmt.Printf("SendMail error: %s\n", err)
        return
    }
    fmt.Println("SendMail ok")

    // OutPut:
    // SendMail ok
}

标签:string,err,读书笔记,adapter,30,content,Go,com,subject
From: https://www.cnblogs.com/brynchen/p/18022893

相关文章

  • MongoDB 入门教程
    基本概念数据库(Database)是集合的容器,相当于关系型DB中的数据库集合(Collection)数据库中的一组文档,相当于SQL中的表文档(Document)集合中的一条记录,相当于SQL的表中的一行。不同的文档之间不必有相同的结构,这一点是和SQL不同的。字段(Field)文档中的键值对,相当于SQL中的列。比......
  • day30 回溯算法总结
     我的感悟:之前一直没看进去,理论篇。今天看了,收获很大。 我的笔记: 资料:卡尔回溯总结卡尔理论视频......
  • [python] [mongoDB] pymongo -- 用python操作mongodb
    官方文档数据库格式mongodb采用了BSON格式,即database->collection->document,在python中,pymongo使用字典来表示一个documnet;document可以包含python原生的数据类型,比如datetime.datetime连接数据库MongoClient连接mongodb,读取数据库,集合和文档CRUD插入Collect......
  • Godot学习中的问题及思考、学习笔记 03
    GameManager类在Godot项目中通常扮演着游戏管理器的角色,负责协调游戏内不同系统、状态和数据的管理。它是一种设计模式,用于集中管理游戏逻辑和状态,使得游戏的结构更加清晰,也便于维护和扩展。GameManager可以处理多种任务,包括但不限于:游戏状态管理:控制游戏的当前状态,比如开始......
  • Go: 如何获取文件所有者
    在Go语言的编程实践中,有时我们需要确定一个文件的所有者是谁。这在处理文件权限、系统管理或安全相关的应用程序时尤其重要。本文将详细介绍如何在Go语言中获取指定文件的所有者信息。前言文件所有者信息是文件系统的一个基本属性,在许多操作系统中都有所体现。在Unix和U......
  • Go: 获取系统用户id示例
    获取当前用户的信息在很多应用程序中,我们需要知道当前正在运行程序的用户是谁。Go语言通过其标准库中的 os/user 包提供了这一功能。示例代码: gopackagemainimport("fmt""os/user")funcmain(){currentUser,err:=user.Current()iferr!=nil{......
  • Django——Ueditor(富文本编辑器)
    富文本编辑器(RichTextEditor,RTE)一种可嵌入浏览器、所见即所得的文本编辑器。富文本编辑器可以方便地嵌入Web应用中以方便用户编辑文章或信息。UEditor是由百度Web前端研发部开发的所见即所得富文本编辑器,具有轻量化、可定制、注重用户体验等特点。基于开源MIT协议,允许自由使用......
  • golang运算符&流程控制
    运算符算数运算funcmain(){ varaint=10 varbint=8 varc=3.14 vard=5.15 fmt.Println(a+b)//18 fmt.Println(a-b)//2 fmt.Println(a*b)//80 fmt.Println(a/b)//1,Go中,如果运算的都是整数,相除后会默认去掉小数,保留整数部分, fmt.Pr......
  • Go语言精进之路读书笔记第29条——使用接口作为程序水平组合的连接点
    如果说C++和Java是关于类型层次结构和类型分类的语言,那么Go则是关于组合的语言。——RobPike,Go语言之父“偏好组合,正交解耦”29.1一切皆组合在语言设计层面,Go提供了诸多正交的语法元素供后续组合使用,包括:Go语言无类型体系(typehierarchy),类型定义独立;方法和类型是正交......
  • 读书笔记3
    第三章软件工程师的成长这章主要讨论软件工程师个人能力衡量及发展,一些思维误区和以后的职业发展在团队工作中,稳定、一致的交付时间时衡量一个员工能力的重要方面初级软件工程师的成长包括以下几种:(1)积累软件开发相关的知识,提升技术技能(如对具体技术的掌握,动手能力)。例如:对JAV......