unit-testing - 在 golang 单元测试中模拟特定的错误类型

标签 unit-testing go testing mocking

我一直致力于处理一些 golang 函数中的软故障,并希望为各种故障场景创建一些单元测试。例如,一些检查包括:

        switch err := err.(type) {
        case net.Error:
                if err.(net.Error).Temporary() || err.(net.Error).Timeout() {
                        ...
                }
        case *url.Error:
                if err, ok := err.Err.(net.Error); ok && err.Timeout() {
                        ...
                }
        case *net.OpError:
                if syscallErr, ok := err.Err.(*os.SyscallError); ok {
                        if syscallErr.Err == syscall.ECONNRESET {
                                ...
                        }
                }
        ...
我相信我只需要我的模拟函数来返回与这些条件兼容的错误。我看到 net.Error、net.OpError、url.Error 和 os.SyscallError 类型已导出。但是,我找不到任何人构造 net.Error 值并返回它的示例——人们投入了大量工作来创建一个以各种方式失败的外部进程,但没有返回带有 Timeout 函数的 net.Error 的示例返回真。
同样,我找不到任何包装不是由 fmt.Errorf 产生的错误的示例,所以我不确定在不使用基本内置错误类型时是否涉及更多的错误。Wrap()。

最佳答案

https://golang.org/pkg/net/#Error是一个接口(interface),定义TimeoutTemporary将是微不足道的,因为它们只是返回 bool .

package main

import(
        "fmt"
        "net"
)

type mockNetError struct {
        temporary bool
        timeout bool
}

func (e *mockNetError)Error() string {
        return fmt.Sprintf("mockNetworkError: timeout %b, temporary %b", e.timeout, e.temporary)
}

func (e *mockNetError)Temporary() bool{
        return e.temporary
}

func (e *mockNetError)Timeout() bool{
        return e.timeout
}
func main() {
        var err error = new(mockNetError)
        if nerr, ok := err.(net.Error); ok {
                fmt.Println("It was a network error! %s", nerr.Error())
        }
}
但是,因为 net.Error是一个接口(interface)类型,err.(type)永远不会归还它。在我的代码中,我断言它可能满足该接口(interface),这与询问它是否是 err 中的值的类型不同。界面。
您在 net 中提到的其他错误不是接口(interface)(尽管它们确实满足 net.Error )。
https://blog.golang.org/go1.13-errors讨论错误包装在 go 中是如何工作的。

a convention rather than a change: an error which contains another may implement an Unwrap method returning the underlying error.


原因%w几乎总是这样做的,因为人们几乎总是在错误中添加额外的文本。
事实上,net.OsError是一个错误示例,它可以通过提供 Unwrap() 来包装另一个错误。方法。
如果您想创建这样的错误,只需:
fmt.Println(net.OpError{
   Op: "mock", 
   Net: "mock",
   Source: &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 1234 },                
   Addr: &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12340 },
   Err: fmt.Errorf("Mock net.OpError"),
})

关于unit-testing - 在 golang 单元测试中模拟特定的错误类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65135710/

相关文章:

html - 如何在 Go 服务器上运行 html

Golang 包不在 GOROOT (/usr/local/go/src/packageName)

go - 如何使用 chromedp 代理

testing - Symfony 4.1 OneToMany 在测试中返回空

PHPUnit 和测试 CRUD 方法

unit-testing - 单元测试应用层

ios - 什么时候使用 specta 的 'sharedExamplesFor' ?

java - 如何使用 JUnit 对 JavaFX Controller 进行单元测试

javascript - Jasmine 测试子类对象是否已通过 Knockout 订阅调用

go - 如何测试表格提交