如何使用 os.O_RDWR 和 os.O_CREATE 标志测试 file.Open?

我正在尝试为结构构造函数编写单元测试,如果在 file.Open 期间发生错误,它也可能返回 nil。我不知道如何使用标志测试/模拟文件错误: os.O_RDWR|os.O_CREATE|os.O_APPEND


我尝试检查测试中的 nil 值,但失败了。


构造函数:


type App struct {

    someField string

    log *log.Logger

}


func New() *App {

    app := &App{}

    f, err := os.OpenFile("info.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

    if err != nil {

        fmt.Printf("error opening file: %v", err)

        return nil

    }

    mw := io.MultiWriter(os.Stdout, f)

    l = log.New(mw, "APP", log.Ldate|log.LstdFlags|log.Lshortfile)

    app.log = l


    return app

}

并测试构造函数:


func TestNew(t *testing.T) {

    var a App

    a = New()


    // doesn't cover

    if a == nil {

        t.Fatal("Error opening file")

    }

}

我希望覆盖错误!= nil,它在覆盖范围内是红色的:


f, err := os.OpenFile("info.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)

if err != nil {

  fmt.Printf("error opening file: %v", err)

  return nil

}


慕丝7291255
浏览 189回答 3
3回答

繁华开满天机

Go 中的模拟意味着拥有接口,如果这是你真正需要的东西,你可能会考虑使用https://github.com/spf13/afero之类的东西,而不是直接使用 os 包。这还允许您使用内存文件系统和其他使测试更容易的东西。

FFIVE

您可以使文件名/文件路径可配置,而不是使用硬编码的 info.log,然后在您的测试中您可以使用一些不存在的路径。有多种配置选项:构造函数中的参数(如果您想保持 API 不变,也许可以从 New 调用一个单独的构造函数)包级别配置(如全局变量 defaultLogFileName),这不太灵活(例如,如果您想并行运行测试),但也可能适合这种情况

慕姐8265434

有两件事需要考虑。第一个是O_RDWR|O_CREAT|O_APPEND在打开文件时几乎没有什么有趣的:它告诉操作系统应该以附加模式打开文件以进行读写,并且如果文件在调用时不存在,则应该被创建,否则可以追加到它上面。现在我认为此操作可能失败的唯一两个原因是:包含该文件的文件系统被挂载为只读 - 因此打开文件进行写入、创建文件并附加到文件是不可能的。该文件不存在,并且文件系统的索引节点表已满,因此即使有空间用于该文件的数据,也无法为另一个文件创建记录。现在考虑一下,为了模拟其中一种情况,您需要操作运行测试的进程可用的一些文件系统。虽然它当然可以在单元测试框架内完成,但它看起来更属于集成测试领域。在 Linux 上进行这一级别的测试有很多选择:“flakey”设备映射器目标和朋友,通过循环设备或 FUSE 安装只读映像,将故障注入正在运行的内核等。不过,这些大多是不适合单元测试。如果你想对这些东西进行单元测试,有两种方法:使用https://github.com/spf13/afero之类的东西抽象出整个文件系统层。好处是您可以轻松测试代码中几乎所有与文件系统相关的内容。使用变量抽象出一点代码。说吧,你可能有var whateverCreate = os.Create在您的代码中使用它whateverCreate,然后在测试套件的设置代码中覆盖该变量,为其分配一个函数,该函数返回您在特定测试中需要的任何错误。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go