How do you convince the when-to-fire-logic to act on a mock, if the torpedo implementation is not provided from outside it?
I'm wondering if I have the terminology understood differently to other people, because to me, DI == IoC. DI Frameworks are build on top of the concept that dependencies will be injected, but doing it explicitly in your start-up code is the same thing to me.
This is the same conversation I had with the new hire I mentioned. And as the other comment here mentioned, it's JavaScript. You simply overwrite the object method with the mock at runtime of the test, then restore it after the test finishes running.
Most JS testing frameworks do this under the hood I believe, without any change in how you write your code. It's a fundamental difference in how JavaScript handles things versus something stricter like C#.
It's a dangerous footgun if you use it carelessly, of course. But a useful language feature when applied carefully.
Right. Facepalm. I kind of missed the bit where we shifted paradigms.
My personal preference would still be to be explicit, to echew secret mutable state even in the tests, but that's just me. My personal baggage makes phrases like "then restore it after the test finishes" bring me out in a cold sweat ;)
I guess I sympathise with your colleague, but I agree it's not idiomatic, and not being idiomatic is not helpful in a team.
In languages like JS/Python, you can mock imports. Actually, sometimes you can mock things defined in the same file if you set things up right.
Basically, the logic not being inlined into the function is enough to provide this behavior in certain languages.
This is not true for other languages, which is why DI frameworks tend to be more useful there.
In go specifically, I just always throw the dependencies behind an interface and shove them into a struct. Then you just create a struct of mocks for your testing.
JS allows you to override global objects, pretty much nothing is constant or immutable in JS. You can (more or less) replace arbitrary functions in any place, at any time.
I'm wondering if I have the terminology understood differently to other people, because to me, DI == IoC. DI Frameworks are build on top of the concept that dependencies will be injected, but doing it explicitly in your start-up code is the same thing to me.