samedi 20 janvier 2018

Mock random generator in Go

For my tests purpose, I would like to mock random numbers in Go. So I created the Random interface. During unit testing I return the identity function, while for implementation I generate a random number with rand package.

It is the right way for mocking random numbers in Go? Any help appreciated.

main:

package main

import (
    "time"
    "math/rand"
    "fmt"
)

func init() {
    rand.Seed(time.Now().UnixNano())
}

type Random interface {
    Uint() uint
}

type rndGenerator func(n uint) uint

type Randomizer struct {
    fn rndGenerator
}

func NewRandomizer(fn rndGenerator) *Randomizer {
    return &Randomizer{fn: fn}
}

func (r *Randomizer) Uint(n uint) uint {
    return r.fn(n)
}

func fakeRand(n uint) uint { return n }
func realRand(_ uint) uint { return uint(rand.Uint64()) }

func main() {
    fakeRnd := NewRandomizer(fakeRand).Uint
    fmt.Println(fakeRnd(1))
    fmt.Println(fakeRnd(2))

    realRnd := NewRandomizer(realRand).Uint
    fmt.Println(realRnd(0))
    fmt.Println(realRnd(0))
}

test:

package main

import (
    "testing"
    "math/rand"
    "reflect"
)

func TestNewRandomizer(t *testing.T) {
    fn := func(n uint) uint { return n }

    type args struct {
        fn rndGenerator
    }
    tests := []struct {
        name string
        args args
        want *Randomizer
    }{
        {
            "test",
            args{fn},
            &Randomizer{fn},
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := NewRandomizer(tt.args.fn); reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
                t.Errorf("NewRandomizer() = %v, want %v", got, tt.want)
            }
        })
    }
}

func TestRandomer_Uint(t *testing.T) {
    rnd := uint(rand.Uint64())

    type fields struct {
        fn rndGenerator
    }
    type args struct {
        n uint
    }
    tests := []struct {
        name   string
        fields fields
        args   args
        want   uint
    }{
        {
            "test",
            fields{func(n uint) uint { return n }},
            args{rnd},
            rnd,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            r := &Randomizer{
                fn: tt.fields.fn,
            }
            if got := r.Uint(tt.args.n); got != tt.want {
                t.Errorf("Randomizer.Uint() = %v, want %v", got, tt.want)
            }
        })
    }
}

func Test_fakeRand(t *testing.T) {
    rnd := uint(rand.Uint64())

    type args struct {
        n uint
    }
    tests := []struct {
        name string
        args args
        want uint
    }{
        {
            "test",
            args{rnd},
            rnd,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := fakeRand(tt.args.n); got != tt.want {
                t.Errorf("fakeRand() = %v, want %v", got, tt.want)
            }
        })
    }
}

func Test_realRand(t *testing.T) {
    type args struct {
        in0 uint
    }
    tests := []struct {
        name string
        args args
        want bool
    }{
        {
            "test",
            args{0},
            true,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := realRand(tt.args.in0); got < 1 {
                t.Errorf("realRand() = %v, want %v", got, tt.want)
            }
        })
    }
}




Aucun commentaire:

Enregistrer un commentaire