You've already forked go-sqlmock
mirror of
https://github.com/DATA-DOG/go-sqlmock.git
synced 2025-06-14 23:55:00 +02:00
update readme and add example
* dcca987 add an old example and a basic one
This commit is contained in:
81
examples/blog/blog.go
Normal file
81
examples/blog/blog.go
Normal file
@ -0,0 +1,81 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type api struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
type post struct {
|
||||
ID int
|
||||
Title string
|
||||
Body string
|
||||
}
|
||||
|
||||
func (a *api) posts(w http.ResponseWriter, r *http.Request) {
|
||||
rows, err := a.db.Query("SELECT id, title, body FROM posts")
|
||||
if err != nil {
|
||||
a.fail(w, "failed to fetch posts: "+err.Error(), 500)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var posts []*post
|
||||
for rows.Next() {
|
||||
p := &post{}
|
||||
if err := rows.Scan(&p.ID, &p.Title, &p.Body); err != nil {
|
||||
a.fail(w, "failed to scan post: "+err.Error(), 500)
|
||||
return
|
||||
}
|
||||
posts = append(posts, p)
|
||||
}
|
||||
if rows.Err() != nil {
|
||||
a.fail(w, "failed to read all posts: "+rows.Err().Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
data := struct {
|
||||
Posts []*post
|
||||
}{posts}
|
||||
|
||||
a.ok(w, data)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// @NOTE: the real connection is not required for tests
|
||||
db, err := sql.Open("mysql", "root@/blog")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
app := &api{db: db}
|
||||
http.HandleFunc("/posts", app.posts)
|
||||
http.ListenAndServe(":8080", nil)
|
||||
}
|
||||
|
||||
func (a *api) fail(w http.ResponseWriter, msg string, status int) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
data := struct {
|
||||
Error string
|
||||
}{Error: msg}
|
||||
|
||||
resp, _ := json.Marshal(data)
|
||||
w.WriteHeader(status)
|
||||
w.Write(resp)
|
||||
}
|
||||
|
||||
func (a *api) ok(w http.ResponseWriter, data interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
a.fail(w, "oops something evil has happened", 500)
|
||||
return
|
||||
}
|
||||
w.Write(resp)
|
||||
}
|
102
examples/blog/blog_test.go
Normal file
102
examples/blog/blog_test.go
Normal file
@ -0,0 +1,102 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
)
|
||||
|
||||
func (a *api) assertJSON(actual []byte, data interface{}, t *testing.T) {
|
||||
expected, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
t.Fatalf("an error '%s' was not expected when marshaling expected json data", err)
|
||||
}
|
||||
|
||||
if bytes.Compare(expected, actual) != 0 {
|
||||
t.Errorf("the expected json: %s is different from actual %s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldGetPosts(t *testing.T) {
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// create app with mocked db, request and response to test
|
||||
app := &api{db}
|
||||
req, err := http.NewRequest("GET", "http://localhost/posts", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("an error '%s' was not expected while creating request", err)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// before we actually execute our api function, we need to expect required DB actions
|
||||
rows := sqlmock.NewRows([]string{"id", "title", "body"}).
|
||||
AddRow(1, "post 1", "hello").
|
||||
AddRow(2, "post 2", "world")
|
||||
|
||||
mock.ExpectQuery("^SELECT (.+) FROM posts$").WillReturnRows(rows)
|
||||
|
||||
// now we execute our request
|
||||
app.posts(w, req)
|
||||
|
||||
if w.Code != 200 {
|
||||
t.Fatalf("expected status code to be 200, but got: %d", w.Code)
|
||||
}
|
||||
|
||||
data := struct {
|
||||
Posts []*post
|
||||
}{Posts: []*post{
|
||||
{ID: 1, Title: "post 1", Body: "hello"},
|
||||
{ID: 2, Title: "post 2", Body: "world"},
|
||||
}}
|
||||
app.assertJSON(w.Body.Bytes(), data, t)
|
||||
|
||||
// we make sure that all expectations were met
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("there were unfulfilled expections: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldRespondWithErrorOnFailure(t *testing.T) {
|
||||
db, mock, err := sqlmock.New()
|
||||
if err != nil {
|
||||
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// create app with mocked db, request and response to test
|
||||
app := &api{db}
|
||||
req, err := http.NewRequest("GET", "http://localhost/posts", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("an error '%s' was not expected while creating request", err)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// before we actually execute our api function, we need to expect required DB actions
|
||||
mock.ExpectQuery("^SELECT (.+) FROM posts$").WillReturnError(fmt.Errorf("some error"))
|
||||
|
||||
// now we execute our request
|
||||
app.posts(w, req)
|
||||
|
||||
if w.Code != 500 {
|
||||
t.Fatalf("expected status code to be 500, but got: %d", w.Code)
|
||||
}
|
||||
|
||||
data := struct {
|
||||
Error string
|
||||
}{"failed to fetch posts: some error"}
|
||||
app.assertJSON(w.Body.Bytes(), data, t)
|
||||
|
||||
// we make sure that all expectations were met
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("there were unfulfilled expections: %s", err)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user