Golang 单元测试中的问题:简单错误。

huangapple go评论120阅读模式
英文:

Golang Issue with Unit Testing for simple error

问题

我正在尝试测试一个内部存在错误的函数,名为ResponseJson。该函数不返回错误,但会发送一个响应的 JSON。以下是该函数的代码:

  1. func ResponseJson(w http.ResponseWriter, Code int, Message string) {
  2. jsonStatus := struct {
  3. Code int `json:"code"`
  4. Message string `json:"message"`
  5. }{
  6. Message: Message,
  7. Code: Code,
  8. }
  9. bs, err := json.Marshal(jsonStatus)
  10. if err != nil {
  11. log.Println("Error in Marshal JSON in ResponseJson:", err)
  12. str := "Internal Server Error. Please contact the System Administrator."
  13. io.WriteString(w, str)
  14. return
  15. } else {
  16. io.WriteString(w, string(bs))
  17. return
  18. }
  19. }

以下是我的单元测试代码,它创建了一个模拟的 ResponseWriter,并且能够成功测试没有错误的情况下的写入响应 JSON。由于 ResponseJson() 函数没有返回错误类型,我该如何在 Test_ResponseJson 函数中测试它呢?

  1. func Test_ResponseJson(t *testing.T) {
  2. responseJsonTests := []struct {
  3. testName string
  4. code int
  5. message string
  6. expectedJsonResponse string
  7. }{
  8. {"Successful Login", http.StatusOK, "Successfully Logged In!", `{"code":200,"message":"Successfully Logged In!"}`},
  9. {"Existing username", http.StatusBadRequest, "Username already exists. Please try again.", `{"code":400,"message":"Username already exists. Please try again."}`},
  10. }
  11. for _, e := range responseJsonTests {
  12. // 创建一个模拟的 ResponseWriter
  13. w := httptest.NewRecorder()
  14. ResponseJson(w, e.code, e.message)
  15. // 将响应体读取为字符串
  16. body, _ := io.ReadAll(w.Result().Body)
  17. actual := string(body)
  18. expected := e.expectedJsonResponse
  19. if actual != expected {
  20. t.Errorf("%s: expected %s but got %s", e.testName, e.expectedJsonResponse, actual)
  21. }
  22. }
  23. }

此外,我创建了一个函数,用于生成 log.Println() 内置函数的实际日志输出。我知道 log.Println() 函数是一个内置函数,很不可能出错。然而,我想在我的单元测试中实现100%的覆盖率。请帮忙!谢谢 Golang 单元测试中的问题:简单错误。

  1. func GenerateLogOutput(message string, errorMessage string) string {
  2. // 创建一个新的 bytes.Buffer 来捕获日志输出
  3. var buf bytes.Buffer
  4. // 将日志输出重定向到一个不同的目标,设置为缓冲区
  5. // 默认情况下,日志消息会被写入标准错误流 os.Stderr
  6. log.SetOutput(&buf)
  7. // 生成一个错误
  8. err := errors.New(errorMessage)
  9. w := httptest.NewRecorder()
  10. // 调用函数
  11. InternalServerError(w, message, err)
  12. actualOutput := buf.String()
  13. return actualOutput
  14. }

以上是你要翻译的内容。

英文:

I am having trouble trying to test this function with an error inside. The following is my ResponseJson function which does not return an error but sends a response json.

  1. func ResponseJson(w http.ResponseWriter, Code int, Message string) {
  2. jsonStatus := struct {
  3. Code int `json:"code"`
  4. Message string `json:"message"`
  5. }{
  6. Message: Message,
  7. Code: Code,
  8. }
  9. bs, err := json.Marshal(jsonStatus);
  10. if err != nil {
  11. log.Println("Error in Marshal JSON in ResponseJson: ", err)
  12. str := "Internal Server Error. Please contact the System Administrator."
  13. io.WriteString(w, str);
  14. return
  15. } else {
  16. io.WriteString(w, string(bs));
  17. return
  18. }
  19. }

The following is my unit testing code which creates a mock ResponseWriter and it is able to successfully test the writer response json for cases with no errors. Since I am not returning an error type in ResponseJson() function, how do I test it inside the Test_ResponseJson function as shown below?

  1. func Test_ResponseJson(t *testing.T) {
  2. responseJsonTests := []struct {
  3. testName string
  4. code int
  5. message string
  6. expectedJsonResponse string
  7. } {
  8. {"Successful Login", http.StatusOK, "Successfully Logged In!", `{"code":200,"message":"Successfully Logged In!"}`},
  9. {"Existing username", http.StatusBadRequest, "Username already exists. Please try again.", `{"code":400,"message":"Username already exists. Please try again."}`},
  10. }
  11. for _, e := range responseJsonTests {
  12. // Creating a mock ResponseWriter
  13. w := httptest.NewRecorder()
  14. ResponseJson(w, e.code, e.message)
  15. // Read the response body as a string
  16. body, _ := io.ReadAll(w.Result().Body)
  17. actual := string(body)
  18. expected := e.expectedJsonResponse
  19. if actual != expected {
  20. t.Errorf("%s: expected %s but got %s", e.testName, e.expectedJsonResponse, actual)
  21. }
  22. }
  23. }

Also, I have created a function which generates an actual log output for log.Println() built-in function. I am aware that the log.Println() function is a built-in function and it is highly unlikely to fail. However, I want to achieve 100% coverage in my unit testing. Please help! Thank you Golang 单元测试中的问题:简单错误。

  1. func GenerateLogOutput(message string, errorMessage string) string {
  2. // Create a new bytes.Buffer to capture the log output
  3. var buf bytes.Buffer
  4. // Redirect log output to a different destination set as a buffer
  5. // By default, log message are written to the standard error stream os.Stderr
  6. log.SetOutput(&buf)
  7. // Generate an error
  8. err := errors.New(errorMessage)
  9. w := httptest.NewRecorder()
  10. // Calling the function
  11. InternalServerError(w, message, err)
  12. actualOutput := buf.String()
  13. return actualOutput
  14. }

答案1

得分: 1

简单来说,我们可以编写一个针对ResponseJson函数的测试用例,如下所示。

  1. func Test_ResponseJson(t *testing.T) {
  2. tests := []struct {
  3. Code int
  4. Message string
  5. ExpectedStr string
  6. }{
  7. {
  8. Code: 1,
  9. Message: "sample message",
  10. ExpectedStr: `{"code":1,"message":"sample message"}`,
  11. },
  12. }
  13. for _, test := range tests {
  14. w := httptest.NewRecorder()
  15. ResponseJson(w, test.Code, test.Message)
  16. res := w.Result()
  17. data, err := ioutil.ReadAll(res.Body)
  18. res.Body.Close()
  19. actualStr := string(data)
  20. assert.Nil(t, err, "Invalid test data")
  21. assert.Equal(t, actualStr, test.ExpectedStr)
  22. }
  23. }

我们无法从bs, err := json.Marshal(jsonStatus)中获得错误。json.Marshal函数可以返回两种类型的错误。

  1. UnsupportedTypeError(例如:通道、复杂和函数值)
  2. UnsupportedValueError(例如:循环数据结构)

我们无法解析值以生成上述任何一种错误。我们正在解析具有支持的值和支持的类型的结构体。因此,我们无法编写具有100%覆盖率的测试。

英文:

Simply, We can write a test case for the ResponseJson function as below.

  1. func Test_ResponseJson(t *testing.T) {
  2. tests := []struct {
  3. Code int
  4. Message string
  5. ExpectedStr string
  6. }{
  7. {
  8. Code: 1,
  9. Message: "sample message",
  10. ExpectedStr: "{\"code\":1,\"message\":\"sample message\"}",
  11. },
  12. }
  13. for _, test := range tests {
  14. w := httptest.NewRecorder()
  15. ResponseJson(w, test.Code, test.Message)
  16. res := w.Result()
  17. data, err := ioutil.ReadAll(res.Body)
  18. res.Body.Close()
  19. actualStr := string(data)
  20. assert.Nil(t, err, "Invalid test data")
  21. assert.Equal(t, actualStr, test.ExpectedStr)
  22. }
  23. }

We cannot get an error from bs, err := json.Marshal(jsonStatus). The json.Marshal function can return two types of errors.

  1. UnsupportedTypeError (ex: channel, complex, and function values)
  2. UnsupportedValueError (ex: cyclic data structures)

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

huangapple
  • 本文由 发表于 2023年3月12日 10:02:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75710686.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定