Home  >  Article  >  Backend Development  >  Simple error problem in Golang unit testing

Simple error problem in Golang unit testing

WBOY
WBOYforward
2024-02-13 20:51:16554browse

Golang 单元测试的简单错误问题

Golang unit testing is an important means to ensure code quality and functional correctness, but in practice, we often encounter some simple errors. In this article, PHP editor Zimo will introduce you to some common error problems and how to solve them. By learning the solutions to these problems, I believe that everyone can perform Golang unit testing more smoothly and improve the quality and reliability of the code.

Question content

I'm having trouble trying to test this function, but there's an error inside. Below is my responsejson function which does not return an error but sends the response json.

func responsejson(w http.responsewriter, code int, message string) {
    jsonstatus := struct {
        code int `json:"code"`
        message string `json:"message"`
    }{
        message: message,
        code: code,
    }

    bs, err := json.marshal(jsonstatus);

    if err != nil {
        log.println("error in marshal json in responsejson: ", err)
        str := "internal server error. please contact the system administrator."
        io.writestring(w, str);
        return 
    } else {
        io.writestring(w, string(bs));
        return
    }
    
}

The following is my unit test code, which creates a mock responsewriter that successfully tests the writer's response to json without errors. Since I am not returning the error type in responsejson() function, how can I test it in test_responsejson function like below?

func test_responsejson(t *testing.t) {
    responsejsontests := []struct {
        testname string
        code int
        message string
        expectedjsonresponse string
    } {
        {"successful login", http.statusok, "successfully logged in!", `{"code":200,"message":"successfully logged in!"}`},
        {"existing username", http.statusbadrequest, "username already exists. please try again.", `{"code":400,"message":"username already exists. please try again."}`},
    }

    for _, e := range responsejsontests {
        // creating a mock responsewriter
        w := httptest.newrecorder()

        responsejson(w, e.code, e.message)

        // read the response body as a string
        body, _ := io.readall(w.result().body)
        actual := string(body)

        expected := e.expectedjsonresponse
        if actual != expected {
            t.errorf("%s: expected %s but got %s", e.testname, e.expectedjsonresponse, actual)
        }
    }
}

Additionally, I created a function that generates the actual log output for the log.println() built-in function. I know that the log.println() function is a built-in function and it is unlikely to fail. However, I want to achieve 100% coverage in my unit tests. please help! Thanks:)

func GenerateLogOutput(message string, errorMessage string) string {
    // Create a new bytes.Buffer to capture the log output
    var buf bytes.Buffer

    // Redirect log output to a different destination set as a buffer
    // By default, log message are written to the standard error stream os.Stderr
    log.SetOutput(&buf)

    // Generate an error
    err := errors.New(errorMessage)

    w := httptest.NewRecorder()

    // Calling the function
    InternalServerError(w, message, err)
    actualOutput := buf.String()

    return actualOutput
}

Solution

Simply put, we can write a test case for the responsejson function as shown below.

func Test_ResponseJson(t *testing.T) {
    tests := []struct {
        Code        int
        Message     string
        ExpectedStr string
    }{
        {
            Code:        1,
            Message:     "sample message",
            ExpectedStr: "{\"code\":1,\"message\":\"sample message\"}",
        },
    }
    for _, test := range tests {
        w := httptest.NewRecorder()

        ResponseJson(w, test.Code, test.Message)

        res := w.Result()
        data, err := ioutil.ReadAll(res.Body)
        res.Body.Close()

        actualStr := string(data)

        assert.Nil(t, err, "Invalid test data")
        assert.Equal(t, actualStr, test.ExpectedStr)
    }
}

We cannot get the error from bs, err := json.marshal(jsonstatus). json.marshal The function can return two types of errors.

  1. unsupportedtypeerror (for example: channels, composite values, and function values)
  2. unsupportedvalueerror (for example: circular data structure)

We were unable to parse the value to generate one of the above errors. We are parsing a struct with supported values ​​and supported types. Therefore, we cannot write tests with 100% coverage.

The above is the detailed content of Simple error problem in Golang unit testing. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete