Add a check that all registered commands have been executed the desired number of times.
Closed this issue · 3 comments
mantyr commented
Example:
func (c *Conn) AssertRequestNumbers(t *testing.T)
I have a solution and I'm ready to do PR.
rafaeljusto commented
Hi @mantyr, why not check the number of calls of each command with the Conn.Stats? Also, adding a library dependency with the testing package doesn't appear to be a good practice.
mantyr commented
I think about two things:
- Programmers often do not do about such verification, Assert helps to avoid this problem
- It may be worthwhile to completely switch to tests with run a real database, this is not always possible, but this is one way to improve the quality of the code.
Problems:
- Integrate the expected number of starts into the familiar Command
- Learn how to write tests for Asserts, what would make a good PR
rafaeljusto commented
@mantyr sorry for the delay. You can already do what you want with the current library API. Check the following example:
redigomock-issue36.go
package main
import (
"fmt"
"os"
"github.com/garyburd/redigo/redis"
)
const (
redisAddress = "127.0.0.1:6379"
)
type Person struct {
Name string `redis:"name"`
Age int `redis:"age"`
}
func addPerson(conn redis.Conn, id string, person Person) error {
_, err := conn.Do("HMSET", redis.Args{}.Add(fmt.Sprintf("person:%s", id)).AddFlat(person)...)
return err
}
func retrievePerson(conn redis.Conn, id string) (Person, error) {
var person Person
values, err := redis.Values(conn.Do("HGETALL", fmt.Sprintf("person:%s", id)))
if err != nil {
return person, err
}
err = redis.ScanStruct(values, &person)
return person, err
}
func addAndRetrievePerson(conn redis.Conn, id string, person Person) (Person, error) {
if err := addPerson(conn, id, person); err != nil {
return Person{}, err
}
return retrievePerson(conn, id)
}
func Job(conn redis.Conn) error {
person, err := addAndRetrievePerson(conn, "1", Person{
Name: "Mr. Johnson",
Age: 42,
})
if err != nil {
return err
}
println(person.Name, person.Age)
person, err = addAndRetrievePerson(conn, "2", Person{
Name: "Mr. Tompson",
Age: 53,
})
if err != nil {
return err
}
println(person.Name, person.Age)
person, err = addAndRetrievePerson(conn, "2", Person{
Name: "Mr. Tompson",
Age: 53,
})
if err != nil {
return err
}
println(person.Name, person.Age)
return nil
}
func main() {
c, err := redis.Dial("tcp", redisAddress, redis.DialPassword("abc123"))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer c.Close()
if err = Job(c); err != nil {
fmt.Println(err)
os.Exit(2)
}
}
Now let's test the Job
function looking for how many times the commands were called.
redigomock-issue36_test.go
package main
import (
"reflect"
"testing"
"github.com/rafaeljusto/redigomock"
)
func TestJob(t *testing.T) {
c := redigomock.NewConn()
scenarios := []struct {
description string
stub func() map[string]*redigomock.Cmd
expected map[string]int
expectedError error
}{
{
description: "it should add and retrieve correctly",
stub: func() map[string]*redigomock.Cmd {
cmds := make(map[string]*redigomock.Cmd)
cmds["HMSET-PERSON1"] = c.Command("HMSET", "person:1", "name", "Mr. Johnson", "age", 42).Expect(int64(1))
cmds["HMSET-PERSON2"] = c.Command("HMSET", "person:2", "name", "Mr. Tompson", "age", 53).Expect(int64(1))
cmds["HGETALL-PERSON1"] = c.Command("HGETALL", "person:1").ExpectMap(map[string]string{
"name": "Mr. Johnson",
"age": "42",
})
cmds["HGETALL-PERSON2"] = c.Command("HGETALL", "person:2").ExpectMap(map[string]string{
"name": "Mr. Tompson",
"age": "53",
})
return cmds
},
expected: map[string]int{
"HMSET-PERSON1": 1,
"HMSET-PERSON2": 2,
"HGETALL-PERSON1": 1,
"HGETALL-PERSON2": 2,
},
},
}
for _, scenario := range scenarios {
t.Run(scenario.description, func(t *testing.T) {
c.Clear()
cmds := scenario.stub()
err := Job(c)
for id, cmd := range cmds {
expectedCalls := scenario.expected[id]
delete(scenario.expected, id)
if calls := c.Stats(cmd); calls != expectedCalls {
t.Errorf("unexpected command call times for id “%s”. Expected “%d” and got “%d”", id, expectedCalls, calls)
}
}
for id := range scenario.expected {
t.Errorf("command id “%s” not called", id)
}
if !reflect.DeepEqual(scenario.expectedError, err) {
t.Errorf("unexpected error. Expected “%#v” and got “%#v”", scenario.expectedError, err)
}
})
}
}