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

PHPz
Release: 2024-02-15 14:06:07
forward
495 people have browsed it

在迭代测试结构时使用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
}
Copy after login

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,
},
Copy after login

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 {
        // ...
    }
})
Copy after login

However, using errors.as as described above returns

second argument to errors.As should not be *error
Copy after login

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())
}
Copy after login

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!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template