Introduction to Golang unit testing

Unit tests are for functions or methods, requiring developers to write one or more sets of test cases for each function or method, covering as many possible scenarios as possible.

In Golang, if you want to unit test the function func GetApp(), the corresponding test function should be named func TestGetApp(). The unit test functions should be in a new file named xx_test.go, corresponding to the code files one by one.

Pile a function or method: Each unit test function or method needs to be independent of network or database connections and run locally. Therefore, you need to replace the logic code related to network connection and database connection in the function or method in the original code, and let the unit test perform a fake network/database connection.

Piling for global variables: The execution of a function or method may depend on global variables and cannot run independently. You can pile dependent global variables in a unit test function or method so that the function or method can run independently.

Gomonkey supports piling for functions, piling for methods, piling for sequences of functions, piling for sequences of methods, and piling for global variables. For the more complex parameters of the function or method, I prefer to use the sequence piling way, can avoid writing complex parameters.

Goconvey can be nested, typically with a test case inside a Convey.

Sqlmock matches SQL statements regularly without mocking them function by function (such as Select… The Find…). .

Unit test example 1- Pile for function

func GetCustomer() ([]Customer, error) {
    var customers []Customer
    err := proxy.GetMysqlClient().Select("customer_name").Find(&customers).Error
    return customers, err
}
Copy the code

To mask database connections, you can use piling for functions or piling for sequences of functions. Proxy.getmockmysqlclient replaces the database connection with the replacement virtual database connection.

var mockOnce sync.Once
var mockMysqlClient *gorm.DB
func GetMockMysqlClient(db *sql.DB) *gorm.DB {
    mockOnce.Do(func() {
        var err error
        mockMysqlClient, err = gorm.Open(
            mysql.New(mysql.config{SkipInitializeWithVersion: true, Conn:db}),
            &gorm.config{}
        )
    })
}
Copy the code
func TestGetCustomer() (t *testing.T) { db, mock, err := sqlmock.New() So(err, ShouldBeNil) p := ApplyFunc(proxy.GetMysqlClient, Func () * gorm.db){return proxy.getMockmysqlClient (DB)} defer p.reset () defer db.Close() rows := sqlmock.NewRows([]string{"customer_name"}).AddRow("123) mock.ExpectQuery("SELECT `customer_name` FROM  `customer`").WillReturnRows(rows) var res []Customer res, err := GetCustomer() So(err, nil) So(res[0].CustomerName, ShouldEqual, "123") }Copy the code

Unit test example 2- Piling for functional sequences

func TestGetCustomerHandler() (t *testing.T) { Convey("test GetCustomerHander", t, {outputs := outputs := outputs := outputs := outputs := outputs := outputs: Param{[]Customer{{}}}}} p := ApplyFuncSeq(dao.getcustomers, outputs) // Defer p.reset () if res, ok := CustomerHandler(); ok { So(res.code, ShouldEqual, 200) } }) }Copy the code