为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕丝7291255 2023-07-17 14:04:06
我正在尝试为结构构造函数编写单元测试,如果在 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}
查看完整描述

3 回答

?
繁华开满天机

TA贡献1816条经验 获得超4个赞

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



查看完整回答
反对 回复 2023-07-17
?
FFIVE

TA贡献1797条经验 获得超6个赞

您可以使文件名/文件路径可配置,而不是使用硬编码的 info.log,然后在您的测试中您可以使用一些不存在的路径。

有多种配置选项:

  • 构造函数中的参数(如果您想保持 API 不变,也许可以从 New 调用一个单独的构造函数)

  • 包级别配置(如全局变量 defaultLogFileName),这不太灵活(例如,如果您想并行运行测试),但也可能适合这种情况


查看完整回答
反对 回复 2023-07-17
?
慕姐8265434

TA贡献1813条经验 获得超2个赞

有两件事需要考虑。

第一个是O_RDWR|O_CREAT|O_APPEND在打开文件时几乎没有什么有趣的:它告诉操作系统应该以附加模式打开文件以进行读写,并且如果文件在调用时不存在,则应该被创建,否则可以追加到它上面。

现在我认为此操作可能失败的唯一两个原因是:

  • 包含该文件的文件系统被挂载为只读 - 因此打开文件进行写入、创建文件并附加到文件是不可能的。

  • 该文件不存在,并且文件系统的索引节点表已满,因此即使有空间用于该文件的数据,也无法为另一个文件创建记录。

现在考虑一下,为了模拟其中一种情况,您需要操作运行测试的进程可用的一些文件系统。虽然它当然可以在单元测试框架内完成,但它看起来更属于集成测试领域。

在 Linux 上进行这一级别的测试有很多选择:“flakey”设备映射器目标和朋友,通过循环设备或 FUSE 安装只读映像,将故障注入正在运行的内核等。不过,这些大多是不适合单元测试。

如果你想对这些东西进行单元测试,有两种方法:

  • 使用https://github.com/spf13/afero之类的东西抽象出整个文件系统层。

    好处是您可以轻松测试代码中几乎所有与文件系统相关的内容。

  • 使用变量抽象出一点代码。

    说吧,你可能有

    var whateverCreate = os.Create

    在您的代码中使用它whateverCreate,然后在测试套件的设置代码中覆盖该变量,为其分配一个函数,该函数返回您在特定测试中需要的任何错误。


查看完整回答
反对 回复 2023-07-17
  • 3 回答
  • 0 关注
  • 166 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信