Home  >  Article  >  Backend Development  >  Using errors.As() when iterating the test structure, return the second parameter to errors.As should not be *error

Using errors.As() when iterating the test structure, return the second parameter to errors.As should not be *error

PHPz
PHPzforward
2024-02-15 14:06:07440browse

在迭代测试结构时使用errors.As(),将第二个参数返回给errors.As 不应该是*error

php editor Strawberry found an error while iterating the test structure. When using errors.As(), the second parameter returned to errors.As should be a pointer to error, not an error. This error may cause the program to behave unexpectedly or incorrectly. Therefore, when using errors.As(), be sure to pay attention to the type of the parameter and ensure that a pointer to error is passed to avoid causing problems. This problem may arise when iterating over test structures, so pay special attention when using errors.As().

Question content

I'm currently writing some unit tests for a package where functions can return multiple types of errors. I define the structure as:

tests := []struct {
    name   string
    data   string
    url    string
    status int
}

And want to use errors.as() to find test.err in errors for my tests. The example structure I used in my tests is as follows:

{
    name:   "url not available",
    err:    &url.error{},
    data:   srvdata,
    url:    "a",
    status: http.statusok,
},

I want to use errors.as for a different structure type that implements the errors interface. So as you can see in the structure, I define err as an error. As can be seen, I use &url.error{} which should implement the error interface.

t.run(test.name, func(t *testing.t) {
    data, err := i.getid(url)
    if err != nil {
        require.notnil(t, test.err)
        assert.true(t, errors.as(err, &test.err))
    } else {
        // ...
    }
})

However, using errors.as as described above returns

second argument to errors.As should not be *error

Now from what I understand, errors.as() accepts any as the second argument, so I'm confused why *error can't be used.

I also tried changing the err field in the test structure to interface{}; however, doing so made all assertions pass regardless of whether the target was present in the error.

I can't find how to use errors.as() to achieve a different type of solution that implements the errors interface in a similar way to above, so now I rely on using contains() instead. Wondering if anyone can provide some insight.

Solution

The pointer to the error type does not satisfy the error interface, which is why the second parameter of as is of type any. In order to store the type you want directly in the .err field, the field must also be of type any.

However, since you have wrapped this pointer value in an interface, you will need to use a type assertion or reflection to get the value for inspection:

var testErr any = new(*url.Error)
_, err := http.Get("http://error.error/")

if errors.As(err, testErr) {
    fmt.Println(reflect.ValueOf(testErr).Elem())
}

The above is the detailed content of Using errors.As() when iterating the test structure, return the second parameter to errors.As should not be *error. 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