bytedance / mockey

a simple and easy-to-use golang mock library
Apache License 2.0
556 stars 22 forks source link

UnpatchAll or GetPatches #50

Closed mmosky closed 5 months ago

mmosky commented 5 months ago

Is your feature request related to a problem? Please describe.

In a large project, someone mocks a function and then forgets to unpatch it. This leads to the mocked function continuing to affect other parts of the project, causing unexpected behavior and hard-to-trace bugs.

Describe the solution you'd like

Add function UnpatchAll to remove all patches and restore the original functionality of patched functions and revert them back to their original state, ensuring that no unintended changes or side effects remain in the system. This function should be idempotent.

Add the function GetPatches to retrieve the current patches, solely to detect if there are any patches that remain unapplied.

Sychorius commented 5 months ago

@MMMMMMoSky Mockey already has UnPatchAll. You can use mockey.UnpPatchAll() to unpatch all mocks in current PatchConvey context or all mocks in your test(if not in PatchConvey) In your case, we recommend you to use PatchConvey. All mock will be unpatched when exiting PatchConvey context. You can also do nested patches with it:

// in convey_test.go
func TestUnpatchAll_Convey(t *testing.T) {
    fn1 := func() string {
        return "fn1"
    }
    fn2 := func() string {
        return "fn2"
    }
    fn3 := func() string {
        return "fn3"
    }

    Mock(fn1).Return("mocked").Build()
    if fn1() != "mocked" {
        t.Error("mock fn1 failed")
    }

    PatchConvey("UnpatchAll_Convey", t, func() {
        Mock(fn2).Return("mocked").Build()
        Mock(fn3).Return("mocked").Build()

        PatchConvey("UnpatchAll_Convey inner", func() {
            Mock(fn2).Return("mocked inner").Build()
            convey.So(fn2(), convey.ShouldEqual, "mocked inner")
        })

        convey.So(fn1(), convey.ShouldEqual, "mocked")
        convey.So(fn2(), convey.ShouldEqual, "mocked")
        convey.So(fn3(), convey.ShouldEqual, "mocked")

        UnPatchAll()

        convey.So(fn1(), convey.ShouldEqual, "mocked")
        convey.So(fn2(), convey.ShouldEqual, "fn2")
        convey.So(fn3(), convey.ShouldEqual, "fn3")
    })

    r1, r2, r3 := fn1(), fn2(), fn3()
    if r1 != "mocked" || r2 != "fn2" || r3 != "fn3" {
        t.Error("mock failed", r1, r2, r3)
    }

    UnPatchAll()

    r1, r2, r3 = fn1(), fn2(), fn3()
    if r1 != "fn1" || r2 != "fn2" || r3 != "fn3" {
        t.Error("mock failed", r1, r2, r3)
    }
}
mmosky commented 5 months ago

Nice. And apologies for the interruption, I forgot to check the latest version. My project is currently using an older version.