From d03795257a640512fbde9c438c33fe10c40e04b3 Mon Sep 17 00:00:00 2001 From: samanhappy Date: Wed, 8 May 2024 11:06:02 +0800 Subject: [PATCH] feat: restore PatchInstanceMethod (#20) * restore PatchInstanceMethod * fix global & restore test * fix test --- monkey.go | 14 ++++++++++++++ monkey_test.go | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/monkey.go b/monkey.go index 25e763b..fb34153 100644 --- a/monkey.go +++ b/monkey.go @@ -56,6 +56,20 @@ func Patch(target, replacement interface{}, opts ...Option) *PatchGuard { return &PatchGuard{t, r, o} } +// PatchInstanceMethod replaces an instance method methodName for the type target with replacement +// Replacement should expect the receiver (of type target) as the first argument +func PatchInstanceMethod(target reflect.Type, methodName string, replacement interface{}) *PatchGuard { + m, ok := target.MethodByName(methodName) + if !ok { + panic(fmt.Sprintf("unknown method %s", methodName)) + } + + o := &opt{global: true} + r := reflect.ValueOf(replacement) + patchValue(m.Func, r, o) + return &PatchGuard{m.Func, r, o} +} + // See reflect.Value type value struct { _ uintptr diff --git a/monkey_test.go b/monkey_test.go index dbb28dc..f4c02cc 100644 --- a/monkey_test.go +++ b/monkey_test.go @@ -90,9 +90,9 @@ func (f *f) No() bool { return false } func TestOnInstanceMethod(t *testing.T) { i := &f{} assert(t, !i.No()) - monkey.Patch((*f).No, func(_ *f) bool { return true }) + pg := monkey.PatchInstanceMethod(reflect.TypeOf(i), "No", func(_ *f) bool { return true }) assert(t, i.No()) - assert(t, monkey.UnpatchInstanceMethod(reflect.TypeOf(i), "No")) + pg.Unpatch() assert(t, !i.No()) }