github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/docs/guides/unit_test_guide.md (about) 1 # Unit Test Guide 2 The purpose of this document is to give introduction about unit tests and to help contributors in writing unit tests. 3 4 ## Unit Test 5 6 Read this [article](http://softwaretestingfundamentals.com/unit-testing/) for a simple introduction about unit tests and benefits of unit testing. Go has its own built-in package called testing and command called ```go test```. 7 For more detailed information on golang's builtin testing package read this [document](https://golang.org/pkg/testing/]). 8 9 ## Mocks 10 11 The object which needs to be tested may have dependencies on other objects. To confine the behavior of the object under test, replacement of the other objects by mocks that simulate the behavior of the real objects is necessary. 12 Read this [article](https://medium.com/@piraveenaparalogarajah/what-is-mocking-in-testing-d4b0f2dbe20a) for more information on mocks. 13 14 GoMock is a mocking framework for Go programming language. 15 Read [godoc](https://godoc.org/github.com/golang/mock/gomock) for more information about gomock. 16 17 Mock for an interface can be automatically generated using [GoMocks](https://github.com/golang/mock) mockgen package. 18 19 **Note** There is gomock package in kubeedge vendor directory without mockgen. Please use mockgen package of tagged version ***v1.1.1*** of [GoMocks github repository](https://github.com/golang/mock) to install mockgen and generate mocks. Using higher version may cause errors/panics during execution of you tests. 20 21 There is gomock package in kubeedge vendor directory without mockgen. Please use mockgen package of tagged version ***v1.1.1*** of [GoMocks github repository](https://github.com/golang/mock) to install mockgen and generate mocks. Using higher version may cause errors/panics during execution of you tests. 22 23 Read this [article](https://blog.codecentric.de/en/2017/08/gomock-tutorial/) for a short tutorial of usage of gomock and mockgen. 24 25 ## Ginkgo 26 27 [Ginkgo](https://onsi.github.io/ginkgo/) is one of the most popular framework for writing tests in go. 28 29 Read [godoc](https://godoc.org/github.com/onsi/ginkgo) for more information about ginkgo. 30 31 See a [sample](https://github.com/kubeedge/kubeedge/blob/master/edge/pkg/metamanager/dao/meta_test.go) in kubeedge where go builtin package testing and gomock is used for writing unit tests. 32 33 See a [sample](https://github.com/kubeedge/kubeedge/blob/master/edge/pkg/devicetwin/dtmodule/dtmodule_test.go) in kubeedge where ginkgo is used for testing. 34 35 ## Writing UT using GoMock 36 37 ### Example : metamanager/dao/meta.go 38 39 After reading the code of meta.go, we can find that there are 3 interfaces of beego which are used. They are [Ormer](https://github.com/kubeedge/kubeedge/blob/master/vendor/github.com/astaxie/beego/orm/types.go), [QuerySeter](https://github.com/kubeedge/kubeedge/blob/master/vendor/github.com/astaxie/beego/orm/types.go) and [RawSeter](https://github.com/kubeedge/kubeedge/blob/master/vendor/github.com/astaxie/beego/orm/types.go). 40 41 We need to create fake implementations of these interfaces so that we do not rely on the original implementation of this interface and their function calls. 42 43 Following are the steps for creating fake/mock implementation of Ormer, initializing it and replacing the original with fake. 44 45 1. Create directory mocks/beego. 46 47 2. use mockgen to generate fake implementation of the Ormer interface 48 ```shell 49 mockgen -destination=mocks/beego/fake_ormer.go -package=beego github.com/astaxie/beego/orm Ormer 50 ``` 51 - `destination` : where you want to create the fake implementation. 52 - `package` : package of the created fake implementation file 53 - `github.com/astaxie/beego/orm` : the package where interface definition is there 54 - `Ormer` : generate mocks for this interface 55 56 3. Initialize mocks in your test file. eg meta_test.go 57 ```shell 58 mockCtrl := gomock.NewController(t) 59 defer mockCtrl.Finish() 60 ormerMock = beego.NewMockOrmer(mockCtrl) 61 ``` 62 63 4. ormermock is now a fake implementation of Ormer interface. We can make any function in ormermock return any value you want. 64 65 5. replace the real Ormer implementation with this fake implementation. DBAccess is variable to type Ormer which we will replace with mock implemention 66 ```shell 67 dbm.DBAccess = ormerMock 68 ``` 69 70 6. If we want Insert function of ormer interface which has return types as (int64,err) to return (1 nil), it can be done in 1 line in your test file using gomock. 71 ```shell 72 ormerMock.EXPECT().Insert(gomock.Any()).Return(int64(1), nil).Times(1) 73 ``` 74 75 ``Expect()`` : is to tell that a function of ormermock will be called. 76 77 ``Insert(gomock.Any())`` : expect Insert to be called with any parameter. 78 79 ``Return(int64(1), nil)`` : return 1 and error nil 80 81 ``Times(1)``: expect insert to be called once and return 1 and nil only once. 82 83 So whenever insert is called, it will return 1 and nil, thus removing the dependency on external implementation.