Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

... until you write unit tests, at which point you need either interfaces or global mutable function pointers to swap out underlying implementations with mocks.


I don't know much about Go but in Java and C# mocking frameworks use runtime bytecode manipulation to make it really easy to swap out concrete implementations without needing to create separate interfaces.


> I don't know much about Go but in Java and C# mocking frameworks use runtime bytecode manipulation to make it really easy to swap out concrete implementations without needing to create separate interfaces.

You cannot do that in Go, you need to write interfaces upfront. Or you can't unit test a controller that depends on a repository which concrete implementation relies on a database.

There is no "bytecode manipulation" here, since there is no bytecode.


Go compiles straight to native code, so unless you get a framework to re-write Assembly, it is not going to happen.


X86 assembly rewriting software does exist. Although I'm not aware anyone ever using it for this purpose... yet.

Getting it to the point actual implementations are replaced by mocks at binary level... might be rather challenging.

(In Golang, tests mainly work like this: foo.go tests are in foo_test.go. "go test" would then run the unit tests for foo in foo_test.)

https://www.golang-book.com/books/intro/12


Of course they do exist, but they are very fragile, usually only work in a very specific architecture, compiler version and compilation flags.

As for your test example, it doesn't work if you need to mock a library only available in binary form.


We really need some better solutions to this. Aside from abstraction it also comes with the performance penalty of virtual functions everywhere.

I think we had some good tools to solve this but either threw them away in newer languages or just forgot they were possible. Working with c recently I wanted to mock something and the language obviously couldn't help me so I came up with something along the lines of:

  #ifdef TEST
    #define foo mock_foo
  #endif
This worked for mocking single functions but would need to evolve for more complex code. There are a number of ways to do this from optional includes to compiling test fixtures to their own binaries with the mock implementation being the actual implementation. Both options should work with just about any language to varying degrees of effort.

The biggest barrier to approaches like this is the reliance on IDE's and what they can do. I've never seen an IDE that can handle rules like this, they want to compile the project and control it's structure. In c# for instance, it would be pretty easy to have a mock library with concrete alternative implementations and compile the tests individually, something like:

  csc.exe MyTest.cs MyClassUnderTest.cs /reference MyMockAssembly.dll
This is perhaps even easier in c/c++ where the includes are more explicit. Once you take back control of the compilation process a lot more options open up though.


I don't think we're in disagreement here. I have no qualms with abstractions/interfaces. It's simply a matter of putting the horse before the cart. The implementations should not have to tip-toe around pre-conceived abstractions.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: