问题描述
出于我的测试目的,我想在 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 中的模拟随机生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!