Skip to content

Commit c368d41

Browse files
authored
Merge pull request #13 from vallieres/update-documentation
Update documentation
2 parents 0d27527 + a3fc039 commit c368d41

File tree

2 files changed

+52
-92
lines changed

2 files changed

+52
-92
lines changed

DOCUMENTATION.md

+40-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# go-mocket Documentation
1+
# Documentation
22

33
## Setting Up Tests
44

@@ -14,6 +14,7 @@ import (
1414

1515
func SetupTests() *sql.DB { // or *gorm.DB
1616
mocket.Catcher.Register() // Safe register. Allowed multiple calls to save
17+
mocket.Catcher.Logging = true
1718
// GORM
1819
db, err := gorm.Open(mocket.DriverName, "connection_string") // Can be any connection string
1920
DB = db
@@ -28,10 +29,18 @@ func SetupTests() *sql.DB { // or *gorm.DB
2829

2930
In the snippet above, we intentionally skipped assigning to proper variable DB instance. One of the assumptions is that the project has one DB instance at the time, overriding it with FakeDriver will do the job.
3031

31-
## Simple Chain Usage
32+
## Usage
3233

3334
***
3435

36+
There are two possible ways to use `mocket`:
37+
38+
* Chaining API
39+
* Specifying `FakeResponse` object with all fields manually. Could be useful for cases when mocks stored separately as the list of FakeResponses.
40+
41+
42+
### Simple Chain Usage
43+
3544
```go
3645
// Function to tests
3746
func GetUsers(db *sql.DB) []map[string]string {
@@ -62,7 +71,9 @@ func TestResponses(t *testing.T) {
6271
SetupTests()
6372

6473
t.Run("Simple SELECT caught by query", func(t *testing.T) {
65-
Catcher.Logging = false
74+
Catcher.Logging = true
75+
// Important: Use database files here (snake_case) and not struct variables (CamelCase)
76+
// eg: first_name, last_name, date_of_birth NOT FirstName, LastName or DateOfBirth
6677
commonReply := []map[string]interface{}{{"user_id": 27, "name": "FirstLast", "age": "30"}}
6778
Catcher.Reset().NewMock().WithQuery(`SELECT name FROM users WHERE`).WithReply(commonReply)
6879
result := GetUsers(DB) // Global or local variable
@@ -78,13 +89,16 @@ func TestResponses(t *testing.T) {
7889
In the example above, we create a new mock via `.NewMock()` and attach a query pattern which will be used to catch a matched query. `.WithReply()` specifies which response will be provided during the mock of this request.
7990
As `Catcher` is global variable without calling `.Reset()` this mock will be applied to all subsequent tests and queries if the pattern matches.
8091

81-
## Usage via `FakeResponse` Object
92+
### Usage via `FakeResponse` Object
8293

8394
We are taking `GetUsers` from the previous example and an example on how it can be using a FakeResponse directly attached to the Catcher object
8495

8596
```go
8697
t.Run("Simple select with direct object", func(t *testing.T) {
8798
Catcher.Reset()
99+
Catcher.Logging = true
100+
// Important: Use database files here (snake_case) and not struct variables (CamelCase)
101+
// eg: first_name, last_name, date_of_birth NOT FirstName, LastName or DateOfBirth
88102
commonReply := []map[string]interface{}{{"user_id": 27, "name": "FirstLast", "age": "30"}}
89103
Catcher.Attach([]*FakeResponse{
90104
{
@@ -105,13 +119,18 @@ t.Run("Simple select with direct object", func(t *testing.T) {
105119

106120
## GORM Example
107121

122+
***
123+
108124
Usage of a mocked GORM is completely transparent. You need to know which query will be generated by GORM and mock them or mock just by using arguments. In this case, you need to pay attention to order of arguments as GORM will not necessarily arrange them in order you provided them.
109125

110126
*Tip:* To identify the exact query generated by GORM you can look at the console output when running your mocked DB connection. They show up like this:
111127
```
112128
2018/01/01 12:00:01 mock_catcher: check query: INSERT INTO "users" ("name") VALUES (?)
113129
```
114-
130+
Just make sure you enable logging like so:
131+
```
132+
Catcher.Logging = true
133+
```
115134

116135
## More Examples
117136

@@ -127,13 +146,15 @@ Please note these two important facts:
127146

128147
```go
129148
t.Run("Catch by arguments", func(t *testing.T) {
130-
commonReply := []map[string]interface{}{{"name": "FirstLast", "age": "30"}}
131-
Catcher.Reset().NewMock().WithArgs(int64(27)).WithReply(commonReply)
132-
result := GetUsers(DB)
133-
if len(result) != 1 {
134-
t.Fatalf("Returned sets is not equal to 1. Received %d", len(result))
135-
}
136-
// all other checks from reply
149+
// Important: Use database files here (snake_case) and not struct variables (CamelCase)
150+
// eg: first_name, last_name, date_of_birth NOT FirstName, LastName or DateOfBirth
151+
commonReply := []map[string]interface{}{{"name": "FirstLast", "age": "30"}}
152+
Catcher.Reset().NewMock().WithArgs(int64(27)).WithReply(commonReply)
153+
result := GetUsers(DB)
154+
if len(result) != 1 {
155+
t.Fatalf("Returned sets is not equal to 1. Received %d", len(result))
156+
}
157+
// all other checks from reply
137158
})
138159
```
139160

@@ -143,6 +164,10 @@ Mocks marked as Once, will not be match on subsequent queries.
143164
```go
144165
t.Run("Once", func(t *testing.T) {
145166
Catcher.Reset()
167+
// Important: Use database files here (snake_case) and not struct variables (CamelCase)
168+
// eg: first_name, last_name, date_of_birth NOT FirstName, LastName or DateOfBirth
169+
commonReply := []map[string]interface{}{{"name": "FirstLast"}}
170+
146171
Catcher.Attach([]*FakeResponse{
147172
{
148173
Pattern:"SELECT name FROM users WHERE",
@@ -249,18 +274,18 @@ Catcher.Reset().NewMock().WithQuery(`SELECT * FROM "users" WHERE`).WithReply(co
249274
```
250275

251276
### Reply Matching
252-
When you provide a Reply to Catcher, your field names must match your database model or else, they will not be updated with the right value.
277+
When you provide a Reply to Catcher, your *field names must match your database model* and NOT the struct object or else, they will not be updated with the right value.
253278

254279
Given you have this test code:
255280
```go
256-
// DO NOT USE, CODE NOT WORKING
281+
// *** DO NOT USE, CODE NOT WORKING ***
257282
commonReply := []map[string]interface{}{{"userID": 7, "name": "FirstLast", "age": "30"}}
258283
mocket.Catcher.NewMock().OneTime().WithQuery(`SELECT * FROM "dummies"`).WithReply(commonReply)
259284

260285
result := GetUsers(DB)
261286
```
262287

263-
This will work and not error out, but `result` will have a 0 value in the field `userID`. You must make sure to match the Reply fields with the database fields and not the struct fields or else you might bang your head on your keyboard.
288+
This will seem to work and not error out, but `result` will have a 0 value in the field `userID`. You must make sure to match the Reply fields with the database fields and not the struct fields or else you might bang your head on your keyboard.
264289

265290
The following code works:
266291
```go
@@ -269,6 +294,3 @@ The following code works:
269294

270295
result := GetUsers(DB)
271296
```
272-
273-
__More examples coming....__
274-

README.md

+12-74
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,35 @@
11
[![GoDoc](https://godoc.org/github.com/Selvatico/go-mocket?status.svg)](https://godoc.org/github.com/Selvatico/go-mocket) [![Build Status](https://travis-ci.org/Selvatico/go-mocket.svg?branch=master)](https://travis-ci.org/Selvatico/go-mocket) [![Go Report Card](https://goreportcard.com/badge/github.com/Selvatico/go-mocket)](https://goreportcard.com/report/github.com/Selvatico/go-mocket)
22

3-
### Go-Mocket
3+
# Go-Mocket – Go GORM & SQL Mocking Library
44

5-
Go-Mocket is library inspired by [DATA-DOG/go-sqlmock](https://github.com/DATA-DOG/go-sqlmock)
6-
As inspiration library, it is the implementation of [sql/driver](https://godoc.org/database/sql/driver) interface but at the same time follows different approaches and has only a similar API.
7-
This library helps to mock any DB connection also with [jinzhu/gorm](https://github.com/jinzhu/gorm), and it was the main goal to create it
5+
Go-Mocket is a library inspired by [DATA-DOG/go-sqlmock](https://github.com/DATA-DOG/go-sqlmock).
6+
7+
As an inspiration library, it is the implementation of [sql/driver](https://godoc.org/database/sql/driver) interface but at the same time it follows a different approach and only has a similar API.
8+
This library helps to mock any DB connection with [jinzhu/gorm](https://github.com/jinzhu/gorm), as it was the created to serve this purpose.
89

910
List of features in the library:
1011

1112
* Mock `INSERT`, `UPDATE`, `SELECT`, `DELETE`
12-
* Support of transactions
13+
* Support for transactions
1314
* 2 API's to use - `chaining` and via specifying a whole mock object
1415
* Matching by prepared statements arguments
1516
* You don't require to change anything inside your code to start using this library
1617
* Ability to trigger exceptions
17-
* Attach callbacks to mocked response to add an additional check or modify a response
18+
* Attach callbacks to mocked responses to add an additional check or modify a response
1819

19-
**NOTE**, Please be aware that driver catches SQL without DB specifics. Generating of queries is done by *SQL* package
20+
**NOTE**, Please be aware that driver catches SQL without DB specifics. Generation of queries is done by *SQL* package
2021

21-
#### Install
22+
## Install
2223

2324
```
2425
go get github.com/Selvatico/go-mocket
2526
```
2627

27-
#### Usage
28-
29-
There are two possible ways to use `mocket`:
30-
31-
* Chaining API
32-
* Specifying `FakeResponse` object with all fields manually. Could be useful for cases when mocks stored separately as the list of FakeResponses.
33-
34-
##### Enabling driver
35-
36-
Somewhere in your code, do this to set up a tests
37-
38-
```go
39-
import (
40-
"database/sql"
41-
mocket "github.com/Selvatico/go-mocket"
42-
"github.com/jinzhu/gorm"
43-
)
44-
45-
func SetupTests() {
46-
mocket.Catcher.Register()
47-
// GORM
48-
db, err := gorm.Open(mocket.DriverName, "any_string") // Could be any connection string
49-
app.DB = db // Assumption that it will be used everywhere the same
50-
//OR
51-
// Regular sql package usage
52-
db, err := sql.Open(mocket.DriverName, "any_string")
53-
}
54-
```
55-
56-
Now, if you use a singleton instance of DB, it will use a mocked connection everywhere.
57-
58-
##### Chain usage
59-
60-
###### Example of mocking by pattern
61-
62-
```go
63-
import mocket "github.com/Selvatico/go-mocket"
64-
import "net/http/httptest"
65-
66-
func TestHandler(t *testing.T) {
67-
request := httptest.NewRequest("POST", "/application", nil)
68-
recorder := httptest.NewRecorder()
69-
70-
GlobalMock := mocket.Catcher
71-
GlobalMock.Logging = true // log mocket behavior
72-
73-
// field names here mapped to the database schema
74-
commonReply := []map[string]interface{}{{"some_id": "2", "field": "value"}}
75-
// Mock only by query pattern
76-
GlobalMock.NewMock().WithQuery(`"campaigns".name IS NULL AND (("uuid" = test_uuid))`).WithReply(commonReply)
77-
Post(recorder, request) // call handler
78-
79-
r := recorder.Result()
80-
body, _ := ioutil.ReadAll(r.Body)
81-
82-
// some assertion about results
83-
//...
84-
}
85-
86-
```
87-
88-
### Documentation
89-
90-
91-
For More Documentation please check [Wiki Documentation](https://github.com/Selvatico/go-mocket/wiki/Documentation)
28+
## Documentation
9229

93-
### License
30+
For detailed usage and examples, look at the [Documentation](https://github.com/Selvatico/go-mocket/blob/master/DOCUMENTATION.md)
9431

32+
## License
9533

9634
MIT License
9735

0 commit comments

Comments
 (0)