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

Discussion: is interface just for mocking a good idea? #770

Closed
xhd2015 opened this issue Mar 30, 2024 · 1 comment
Closed

Discussion: is interface just for mocking a good idea? #770

xhd2015 opened this issue Mar 30, 2024 · 1 comment

Comments

@xhd2015
Copy link

xhd2015 commented Mar 30, 2024

This is not an issue, but a discussion about mocking.

There used to be lots of code in our legacy codebase, lacking unit tests. We are gradually adding test to it but found existing tools have their own pros and cons, listed below:

  • go-monkey
    • easy to get started, but suddenly break some day
  • go-mock by google
    • too hard to get started, need to learn a new set of toolchain
  • mockery
    • still, interface everywhere

Basically, interface based mocking enforces the code to be written in one way, the indirect way, just for mock injecting.
And to do that, a lot helper files are generated, and we pretend they do not exist while they are annoying.

Based on my current working requirement, I prefer to use go-monkey. But it has a terrible compatibility, and seems will never be solved.

Thus, I created the xgo library https://github.com/xhd2015/xgo , which solves the monkey patching problem by not utilizing any low level stuff like ASM, but instead preprocess the source code on the fly.

The idea is simple, given a function:

func Add(a, b int) int {
    return a+b
}

We would rewrite it into:

import "runtime"

func Add(a,b int) (r0 int) {
     mocked := runtime.Trap(add, &a, &b, &r0)
     if mocked {
           return
     }
     return a+b
}

The whole thing does not need any setup, except the user adding a build flag -toolexec=xgo when invoking go build, go run or go test. This flag lets xgo preprocess the source code before go compiles them.

So, indeed, it's monkey patching, at source level.

This way, we never need to abstract an interface just for mocking. Actually, it does not enforce any coding style to the code base.

How do you mockery guys think of it? Will you buy this idea?

Let's discuss!

@LandonTClipp
Copy link
Contributor

Hi, thanks for your discussion. I looked over the details of your project and it is indeed very clever. You do not see many projects interacting with Go's IR, so this is a fairly novel (to me) method of what is ultimately a style of dependency injection.

Questions I have:

 Instead, it relies on the IR representation employed by the go compiler.

What guarantees does Go provide on the compatibility of the IR across language versions? Is this essentially identical to the backwards-compatability promise?

Do you have any writing on the specifics of how you do the IR Rewriting? I'm personally interested to hear more.

At the moment, I am not convinced that such a style of DI is somehow superior in theory to interfaces, as it has become a community-wide standard, and as such I fear that you will meet major headwinds against modifying that standard. However, your idea itself is quite interesting and I welcome the discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants