Go 中的模拟随机生成器 [英] Mock random generator in Go

查看:37
本文介绍了Go 中的模拟随机生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于我的测试目的,我想在 Go 中模拟随机数.所以我创建了 Random 接口.在单元测试期间,我返回标识函数,而在实现时,我使用 rand 包生成一个随机数.

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.

这是在 Go 中模拟随机数的正确方法吗?任何帮助表示赞赏.

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

去游乐场:https://play.golang.org/p/bibNnmY2t1g

主要:

package main

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

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

type Random interface {
    Uint(_ 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))
}

测试:

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)
            }
        })
    }
}

推荐答案

我有一个方法可以生成一个随机整数,如果整数小于或等于 50 并且 返回 true如果整数在 [0, 100] 范围内大于 50,则返回 false.

I have a method which generates a random integer and returns true if the integer is less than or equal to 50 and false if the integer is greater than 50 in the range [0, 100).

这就是我创建结构来模拟功能的方式:

This is how I have created my structures to mock the functionality:

type Decider struct {
    RandImpl func(int) int
}

func (d *Decider) Decide(randRange int) bool {
    randVal := d.RandImpl(randRange)
    log.Info("RandVal: ", randVal)
    if randVal <= 50 {
        return true
    }
    return false
}

我以这种方式调用此方法:

I'm calling this method in this manner:

rand.Seed(time.Now().UnixNano())
decider := decide.Decider{
    RandImpl: func(x int) int { return rand.Intn(x) },
}
decider.Decide(100)

在我的 _test.go 文件中,我有这个:

In my _test.go file, I have this:

decider := Decider{
    RandImpl: func(x int) int { return 42 },
}
ret := decider.Decide(100)
assert.True(t, ret)

通过这种方式,您可以模拟随机数生成器的功能.

This way you can mock the functionality of the random number generator.

这篇关于Go 中的模拟随机生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆