【问题标题】:Testing that the API request is working golang测试 API 请求是否正常运行 golang
【发布时间】:2020-05-21 20:23:14
【问题描述】:

我正在尝试向我的 golang 项目添加测试。我的程序正在将 JSON 数据保存到 csv 文件中。我所做的是在屏幕上显示我的数据(参见评论// STDOUT)并使用管道自动创建我想要的格式文件:go run main.go > file.csv,例如在这里我将数据保存到名为 file.csv 的 csv 文件中

为了更清楚,这是我的代码:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "strconv"
    "strings"
)

type People struct {
    Name string
    Craft string
}

type General struct {
    People []People
    Number int
    Message string
}

func main() {
    // Reading data from JSON File  
    response, err := http.Get("http://api.open-notify.org/astros.json")
    if err != nil {
        fmt.Printf("The Http request failed with error %s\n", err)
    }

    data,_ := ioutil.ReadAll(response.Body)
    //fmt.Println(string(data))
    // Unmarshal JSON data
    var general General
    json.Unmarshal([]byte(data), &general)
    var header []string
    header = append(header, "Number")
    header = append(header, "Message")
    header = append(header, "Name")
    header = append(header, "Craft")
    fmt.Println(strings.Join(header, ","))
    for _, obj := range general.People {    
        var record []string
        record = append(record, strconv.Itoa(general.Number), general.Message)
        record = append(record, obj.Name, obj.Craft)
        fmt.Println(strings.Join(record, ",")) // STDOUT 
        record = nil
    }
}

所以在我的屏幕上我按预期获得了这个输出:

Number,Message,Name,Craft
6,success,Christina Koch,ISS
6,success,Alexander Skvortsov,ISS
6,success,Luca Parmitano,ISS
6,success,Andrew Morgan,ISS
6,success,Oleg Skripochka,ISS
6,success,Jessica Meir,ISS

所以我想知道如何测试此输出是否正确显示了我期望的数据。

我试图编写一个main_test.go 文件,但我不知道如何正确编码。

package main

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

func TestGetEntries(t *testing.T) {
    response, err := http.Get("http://api.open-notify.org/astros.json")
    if err != nil {
        t.Fatal(err)
    }
    // I don't know how to deal with this part:
    rr := httptest.NewRecorder()
    handler := http.HandlerFunc(main)
    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)
    }

    // Check the response body is what we expect.
    // For example I want to test the first line:
    expected := `6,success,Christina Koch,ISS`
    if rr.Body.String() != expected {
        t.Errorf("handler returned unexpected body: got %v want %v",
            rr.Body.String(), expected)
    }
}

【问题讨论】:

  • 将对象写入“主列表”,然后将整个列表打印到标准输出。然后您可以针对列表内容进行测试
  • 另外,测试不应该依赖外部服务。使用真实数据 + 一些预期的 HTTP 错误响应创建虚假响应。
  • 单元 测试不应依赖外部服务。 集成测试应该。 OP 没有具体说明这是哪一个。
  • 我不明白你是怎么做到的。

标签: json csv go testing


【解决方案1】:

让我警告一下,我可能有点太喜欢测试了,正常人通常不会太过分。

我通常会尽量避免在 main 中测试将直接打印到 stdout 的内容,在将内容打印到 stdout 之前测试内容是否从函数返回会更容易。

有时我真的希望我的测试覆盖率主要以及在这种情况下可以使用以“示例”为前缀的测试函数,这是一个糟糕的解决方案,但使用起来非常简单。

ma​​in.go

package main
import "fmt"
func main(){
   fmt.Println("Hello World")
}

ma​​in_test.go

package main
func ExampleMain(){
   main()
   // Output:
   // Hello World
}

使用您的代码,“示例”应该是:

package main
func ExampleMain(){
   main()
   // Output:
   // Number,Message,Name,Craft
   // 6,success,Christina Koch,ISS
   // 6,success,Alexander Skvortsov,ISS
   // 6,success,Luca Parmitano,ISS
   // 6,success,Andrew Morgan,ISS
   // 6,success,Oleg Skripochka,ISS
   // 6,success,Jessica Meir,ISS
}

这是一种简单的测试方法,但要保持更新有点困难,所以我不太喜欢它。

我更喜欢像这样更灵活的东西:
ma​​in.go

package main

import "fmt"

func main() {

    txt := helloWorld()

    fmt.Println(txt)
}

func helloWorld() string {
    return "Hello World"
}

ma​​in_test.go

package main

import "testing"

func Test_helloWorld(t *testing.T) {
    tests := []struct {
        name string
        want string
    }{
        {
            name: "A simple Test",
            want: "Hello World",
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := helloWorld(); got != tt.want {
                t.Errorf("helloWorld() = %v, want %v", got, tt.want)
            }
        })
    }
}

最好在您的测试中尽可能不请求外部服务,当然,如果您认为出于任何您知道的原因将其请求到您的测试中更好,那也可以,但如果您觉得这样会更好是一个模拟它的请求,不知道我会很乐意提出一些方法来做到这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 2022-10-17
    • 1970-01-01
    • 2022-08-18
    相关资源
    最近更新 更多