Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom fakeable types #230

Merged
merged 15 commits into from Apr 4, 2023
80 changes: 80 additions & 0 deletions fakeable.go
@@ -0,0 +1,80 @@
package gofakeit

import (
"errors"
"fmt"
"reflect"
)

// Fakeable is an interface that can be implemented by a type to provide a custom fake value.
type Fakeable interface {
// Fake returns a fake value for the type.
Fake(faker *Faker) interface{}
}

func isFakeable(t reflect.Type) bool {
fakeableTyp := reflect.TypeOf((*Fakeable)(nil)).Elem()

return t.Implements(fakeableTyp) || reflect.PtrTo(t).Implements(fakeableTyp)
}

func callFake(faker *Faker, v reflect.Value, possibleKinds ...reflect.Kind) (interface{}, error) {
f, ok := v.Addr().Interface().(Fakeable)
if !ok {
return nil, errors.New("not a Fakeable type")
}

fakedValue := f.Fake(faker)
k := reflect.TypeOf(fakedValue).Kind()
if !contains(possibleKinds, k) {
return nil, fmt.Errorf("returned value kind %q is not amongst the valid ones: %v", k, possibleKinds)
}

switch k {
case reflect.String:
return reflect.ValueOf(fakedValue).String(), nil
case reflect.Bool:
return reflect.ValueOf(fakedValue).Bool(), nil
case reflect.Int:
return int(reflect.ValueOf(fakedValue).Int()), nil
case reflect.Int8:
return int8(reflect.ValueOf(fakedValue).Int()), nil
case reflect.Int16:
return int16(reflect.ValueOf(fakedValue).Int()), nil
case reflect.Int32:
return int32(reflect.ValueOf(fakedValue).Int()), nil
case reflect.Int64:
return int64(reflect.ValueOf(fakedValue).Int()), nil
case reflect.Uint:
return uint(reflect.ValueOf(fakedValue).Uint()), nil
case reflect.Uint8:
return uint8(reflect.ValueOf(fakedValue).Uint()), nil
case reflect.Uint16:
return uint16(reflect.ValueOf(fakedValue).Uint()), nil
case reflect.Uint32:
return uint32(reflect.ValueOf(fakedValue).Uint()), nil
case reflect.Uint64:
return uint64(reflect.ValueOf(fakedValue).Uint()), nil
case reflect.Float32:
return float32(reflect.ValueOf(fakedValue).Float()), nil
case reflect.Float64:
return float64(reflect.ValueOf(fakedValue).Float()), nil
case reflect.Slice:
return reflect.ValueOf(fakedValue).Interface(), nil
case reflect.Map:
return reflect.ValueOf(fakedValue).Interface(), nil
case reflect.Struct:
return reflect.ValueOf(fakedValue).Interface(), nil
default:
return nil, fmt.Errorf("unsupported type %q", k)
}
}

func contains(possibleKinds []reflect.Kind, kind reflect.Kind) bool {
mgilbir marked this conversation as resolved.
Show resolved Hide resolved
for _, k := range possibleKinds {
if k == kind {
return true
}
}
return false
}