duanlu9557 2019-02-12 10:58
浏览 70

具有ORM交互的单元测试Go函数

I have written a function:

func AllItems(w http.ResponseWriter, r *http.Request) {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic("failed to connect database")
    }
    defer db.Close()

    var items [] Item
    db.Find(&items)
    fmt.Println("{}", items)

    json.NewEncoder(w).Encode(items)
}

I want to do unit testing on this. Ideally, unit testing means that each line of the function needs to be tested. I'm not sure how I should test if a database connection is opened and then if it is displaying all the contents of the database. How should I test this code?

This function is the GET endpoint of a simple CRUD application. The code is here.

  • 写回答

1条回答 默认 最新

  • dongxun7962 2019-02-12 12:26
    关注

    Refactor your code and break it down into smaller, testable functions which you pass dependencies to. Also create interfaces for the dependencies to make testing easier.

    For example:

    type myDatabaseInterface interface {
        Find(interface{}) // this signature should match the real db.Find()
    }
    
    func AllItems(w http.ResponseWriter, r *http.Request) {
        db, err := gorm.Open("sqlite3", "test.db")
        if err != nil {
            panic("failed to connect database")
        }
        defer db.Close()
        items := findItems(db)
        json.NewEncoder(w).Encode(items)
    }
    
    func find(db myDatabaseInterface) ([]Item) {
        var items []Item
        db.Find(&items)
        return items
    }
    

    Then you can create mocks for your dependencies and use them in your tests:

    type mock struct {}
    
    // mock should implement myDatabaseInterface to be able to pass it to the function
    func (m *mock) Find(interface{}) {
        // implement the mock to satisfy your test
    }
    
    func Test_find(t *testing.T) {
        m := mock{}
        res := find(m)
        // do testing
    }
    

    Instead of calling Open every time you handle a request maybe you should open it outside and have it available to your function. That way the handler becomes so small there's no need to test it really:

    func makeAllItemsHandler(db myDatabaseInterface) func(http.ResponseWriter, *http.Request) {
        return func(http.ResponseWriter, *http.Request) {
            items := findItems(db)
            json.NewEncoder(w).Encode(items)
        }
    }
    

    Then you can create a db once and for all when you set up your application and pass it to the functions that need it thus removing hard to test code from the functions.

    评论

报告相同问题?

悬赏问题

  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程
  • ¥30 Eclipse官网打不开,官网首页进不去,显示无法访问此页面,求解决方法
  • ¥15 关于smbclient 库的使用
  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?