”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Go API 的基本单元测试 – 充满信心地构建代码

Go API 的基本单元测试 – 充满信心地构建代码

发布于2024-11-08
浏览:517

Essential Unit Testing for Go APIs – Build Code with Confidence

在构建此 API 时,我们涵盖了身份验证、日志记录、Docker 化等内容。但我们还没有讨论的一件事是测试!如果您希望 API 能够投入生产,那么添加可靠的单元测试至关重要。在这篇文章中,我们将介绍 Go 中单元测试的基础知识,以便您可以及早发现错误并交付高质量的代码。

为什么要进行单元测试?

单元测试可帮助您验证代码库的每个部分是否按预期工作。它们是您抵御错误、回归和其他令人讨厌的意外情况的第一道防线。使用 Go 的内置测试库,您可以快速设置测试:

  • 确保您的函数行为一致。
  • 使重构代码变得更容易,而不会引入新问题。
  • 增强您对一切正常运转的信心。

准备好开始了吗?让我们深入了解一下! ?


第 1 步:设置基本测试

Go 的测试框架很简单并且直接集成到语言中。您可以通过使用 _test.go 后缀命名来创建测试文件。让我们首先测试 main.go 中的一个简单函数:

// main.go
package main

func Add(a, b int) int {
    return a   b
}

现在,创建一个名为 main_test.go 的文件并添加以下代码:

// main_test.go
package main

import "testing"

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    expected := 5

    if result != expected {
        t.Errorf("Add(2, 3) = %d; want %d", result, expected)
    }
}

运作原理:

  1. 测试函数:Go中的任何测试函数都必须以Test开头并接受*testing.T参数。
  2. 断言:我们检查结果是否符合我们的预期。如果没有,我们使用 t.Errorf.
  3. 记录错误

要运行测试,只需使用:

go test

如果一切正常,您将看到一条 ok 消息。 ?


第 2 步:测试 HTTP 处理程序

现在,让我们为我们的 HTTP 处理程序之一编写一个测试。我们将使用 Go 的 httptest 包来创建模拟 HTTP 请求和响应记录器。

// main_test.go
package main

import (
    "net/http"
    "net/http/httptest"
    "testing"
)

func TestGetBooksHandler(t *testing.T) {
    req, err := http.NewRequest("GET", "/books", nil)
    if err != nil {
        t.Fatal(err)
    }

    rr := httptest.NewRecorder()
    handler := http.HandlerFunc(getBooks)

    handler.ServeHTTP(rr, req)

    if status := rr.Code; status != http.StatusOK {
        t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK)
    }
}

解释:

  1. httptest.NewRequest:创建一个新的 HTTP 请求。这模拟了对您的 /books 端点的请求。
  2. httptest.NewRecorder:模拟 HTTP 响应。我们稍后会检查它是否符合我们的预期。
  3. ServeHTTP:使用模拟请求和记录器调用我们的 getBooks 处理程序。

这样,您可以隔离和测试您的处理程序,而无需启动完整的服务器。 ?


第 3 步:运行覆盖率测试

Go 有一种内置的方法来检查测试覆盖率。要查看测试覆盖了代码的百分比,您可以运行:

go test -cover

如需更详细的报道,请生成 HTML 报告:

go test -coverprofile=coverage.out
go tool cover -html=coverage.out

打开生成的 HTML 文件以可视化覆盖了代码的哪些部分。这是查看哪里可能需要额外测试的绝佳方法。


第 4 步:模拟外部依赖项

当测试依赖于外部服务的功能(例如数据库或外部API调用)时,您可以使用接口来模拟这些依赖关系。

// Define a simple interface for our database
type Database interface {
    GetBooks() ([]Book, error)
}

// Implement a mock database
type MockDatabase struct{}

func (m MockDatabase) GetBooks() ([]Book, error) {
    return []Book{{Title: "Mock Book"}}, nil
}

通过使用接口,您可以在测试过程中用您的模拟替换实际的依赖关系。这可以让您的测试快速、隔离且可重复。


接下来是什么?

既然您已经开始构建单元测试,请尝试将测试添加到 API 的其他部分! ?下周,我们将研究集成 CI/CD 管道,以便这些测试可以在每次更改时自动运行。敬请关注!


向您提问:您最喜欢的测试工具或技术是什么?请在下面发表评论——我很想听听其他 Go 开发人员如何进行测试!


有了这些基础知识,您就可以编写可靠的测试,使您的 Go API 更加可靠。有关更多测试技巧和高级技术,请继续关注未来的帖子。测试愉快! ?

版本声明 本文转载于:https://dev.to/neelp03/essential-unit-testing-for-go-apis-build-code-with-confidence-ne3?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何避免Go语言切片时的内存泄漏?
    如何避免Go语言切片时的内存泄漏?
    ,a [j:] ...虽然通常有效,但如果使用指针,可能会导致内存泄漏。这是因为原始的备份阵列保持完整,这意味着新切片外部指针引用的任何对象仍然可能占据内存。 copy(a [i:] 对于k,n:= len(a)-j i,len(a); k
    编程 发布于2025-07-17
  • FastAPI自定义404页面创建指南
    FastAPI自定义404页面创建指南
    response = await call_next(request) if response.status_code == 404: return RedirectResponse("https://fastapi.tiangolo.com") else: ...
    编程 发布于2025-07-17
  • 如何在无序集合中为元组实现通用哈希功能?
    如何在无序集合中为元组实现通用哈希功能?
    在未订购的集合中的元素要纠正此问题,一种方法是手动为特定元组类型定义哈希函数,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    编程 发布于2025-07-17
  • 版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    在时间戳列上使用current_timestamp或MySQL版本中的current_timestamp或在5.6.5 此限制源于遗留实现的关注,这些限制需要对当前的_timestamp功能进行特定的实现。 创建表`foo`( `Productid` int(10)unsigned not n...
    编程 发布于2025-07-17
  • 如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    postgresql:为每个唯一标识符提取最后一行,在Postgresql中,您可能需要遇到与在数据库中的每个不同标识相关的信息中提取信息的情况。考虑以下数据:[ 1 2014-02-01 kjkj 在数据集中的每个唯一ID中检索最后一行的信息,您可以在操作员上使用Postgres的有效效率: ...
    编程 发布于2025-07-17
  • Java中如何使用观察者模式实现自定义事件?
    Java中如何使用观察者模式实现自定义事件?
    在Java 中创建自定义事件的自定义事件在许多编程场景中都是无关紧要的,使组件能够基于特定的触发器相互通信。本文旨在解决以下内容:问题语句我们如何在Java中实现自定义事件以促进基于特定事件的对象之间的交互,定义了管理订阅者的类界面。以下代码片段演示了如何使用观察者模式创建自定义事件: args)...
    编程 发布于2025-07-17
  • 如何将PANDAS DataFrame列转换为DateTime格式并按日期过滤?
    如何将PANDAS DataFrame列转换为DateTime格式并按日期过滤?
    将pandas dataframe列转换为dateTime格式示例:使用column(mycol)包含以下格式的以下dataframe,以自定义格式:})指定的格式参数匹配给定的字符串格式。转换后,MyCol列现在将包含DateTime对象。 date oped filtering > = p...
    编程 发布于2025-07-17
  • 如何使用Depimal.parse()中的指数表示法中的数字?
    如何使用Depimal.parse()中的指数表示法中的数字?
    在尝试使用Decimal.parse(“ 1.2345e-02”中的指数符号表示法表示的字符串时,您可能会遇到错误。这是因为默认解析方法无法识别指数符号。 成功解析这样的字符串,您需要明确指定它代表浮点数。您可以使用numbersTyles.Float样式进行此操作,如下所示:[&& && && ...
    编程 发布于2025-07-17
  • 如何使用FormData()处理多个文件上传?
    如何使用FormData()处理多个文件上传?
    )处理多个文件输入时,通常需要处理多个文件上传时,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    编程 发布于2025-07-17
  • 将图片浮动到底部右侧并环绕文字的技巧
    将图片浮动到底部右侧并环绕文字的技巧
    在Web设计中围绕在Web设计中,有时可以将图像浮动到页面右下角,从而使文本围绕它缠绕。这可以在有效地展示图像的同时创建一个吸引人的视觉效果。 css位置在右下角,使用css float and clear properties: img { 浮点:对; ...
    编程 发布于2025-07-17
  • 可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    [2这里: https://webthemez.com/demo/sticky-multi-header-scroll/index.html </main> <section> { display:grid; grid-template-...
    编程 发布于2025-07-17
  • 在Python中如何创建动态变量?
    在Python中如何创建动态变量?
    在Python 中,动态创建变量的功能可以是一种强大的工具,尤其是在使用复杂的数据结构或算法时,Dynamic Variable Creation的动态变量创建。 Python提供了几种创造性的方法来实现这一目标。利用dictionaries 一种有效的方法是利用字典。字典允许您动态创建密钥并分...
    编程 发布于2025-07-17
  • 为什么不使用CSS`content'属性显示图像?
    为什么不使用CSS`content'属性显示图像?
    在Firefox extemers属性为某些图像很大,&& && && &&华倍华倍[华氏华倍华氏度]很少见,却是某些浏览属性很少,尤其是特定于Firefox的某些浏览器未能显示图像时未能显示图像时遇到了一个问题。这可以在提供的CSS类中看到:。googlepic { 内容:url(&#...
    编程 发布于2025-07-17
  • Java中Lambda表达式为何需要“final”或“有效final”变量?
    Java中Lambda表达式为何需要“final”或“有效final”变量?
    Lambda Expressions Require "Final" or "Effectively Final" VariablesThe error message "Variable used in lambda expression shou...
    编程 发布于2025-07-17
  • 如何在其容器中为DIV创建平滑的左右CSS动画?
    如何在其容器中为DIV创建平滑的左右CSS动画?
    通用CSS动画,用于左右运动 ,我们将探索创建一个通用的CSS动画,以向左和右移动DIV,从而到达其容器的边缘。该动画可以应用于具有绝对定位的任何div,无论其未知长度如何。问题:使用左直接导致瞬时消失 更加流畅的解决方案:混合转换和左 [并实现平稳的,线性的运动,我们介绍了线性的转换。这...
    编程 发布于2025-07-17

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3