News for hackers. Stuff that matters.
Re:Warming Up to Unit Testing by war1025 on Monday February 24, 2020 @11:24AM (#22405426)
> If your code base utilizes dependency injection to make the code more "testable" with mocks, you are making the code 10x worse.

I don't know that I'd word it exactly like that, but one thing I've found over the years is any tests we have that rely on mocks basically just don't test anything at all.

If your whole test is "This gets called, then that, then that", you aren't actually writing a test. You're repeating what the code already says.

Re:Warming Up to Unit Testing by crimsonalucard on Monday February 24, 2020 @11:34AM (#22405524)
Well, "something" is being tested as your code is verifying that an input produces an output.

But your philosophy is correct and we are in agreement on that.

The thing I was referring to is the abstraction of dependency injection itself. It leads to code that is over complicated as the abstraction itself is not only pointless but adds unnecessary layers of complexity.

There are ways to target the philosophy of what dependency injection for unit testing is trying to accomplish without introducing the side effect of unnecessary complexity that comes with dependency injection. It's as simple as just separating IO functions from core logical functions. Don't bundle these two things together into an object or a single function, that's it. (Also don't use objects period, but that's another topic.)

Re:Warming Up to Unit Testing by l_t on Monday February 24, 2020 @12:05PM (#22405871)
I like dependency injection even when I'm not writing tests (which I usually skip for side-projects.)

I find it natural and convenient to think about "What dependencies on other parts of the system does this code have?" Expressing those dependencies explicitly feels like it reduces complexity, not adds it.

But, I'm not talking about pulling in a big fancy DI framework, just making dependencies explicit in your function/class parameters.

I will say that DI is sometimes used as a tool in overly-abstracted systems. An example that comes to mind is the ASP.NET MVC framework -- with DI and inheritance, literally any behavior can be overridden in fairly opaque ways. Trying to suss out the concrete behavior details is like swimming in quicksand. (Or it used to be that way, haven't touched ASP.NET in a while.)

As an aside -- I'm curious about your programming language of choice. I think DI is a lot more useful in some PLs than others. For example, I find JS code often uses imports to create complex graphs of implicit dependencies, and DI can help tame that complexity. But for other PLs like Python or Clojure, I basically don't use DI at all.

Re:Warming Up to Unit Testing by bernawil on Monday February 24, 2020 @01:25PM (#22406756)
Javascript doesn't "need" dependency injection because modules are objects, and you can mock those directly by replacing what they reference to. Very similar story in python. You could say people do DI in these dynamic languages without calling it DI.

Now Java and C# are different because they are compiled. You need a DI tool to do dynamic dispatch if you want to mock.

Re:Warming Up to Unit Testing by crimsonalucard on Monday February 24, 2020 @03:18PM (#22407994)
It's all aspects of the same thing.

You can't inject a nuclear reactor into a burrito in any language untyped or not because it will lead to an error.

The only difference is python/js the error will happen at runtime while in C$/java the error happens at compile time.

The main difference is the type. In typed languages you need describe am interface or a class of types if you want to do mocking or dynamic dispatch while in dynamic languages you don't need to explicitly define this as a type, the definition exists in how you use the object that is passed in.

Either way DI, however universal, in any language is bad practice.

Re:Warming Up to Unit Testing by sgtnoodle on Monday February 24, 2020 @01:48PM (#22407057)
Good dependency injection results in flatter code rather than more layers. Dependency injection simply moves the dependencies to the top of the program rather than the bottom.
Re:Warming Up to Unit Testing by Seenso on Monday February 24, 2020 @12:30PM (#22406127)
> If your whole test is "This gets called, then that, then that", you aren't actually writing a test. You're repeating what the code already says.

Yeah, mocks are just a way to zero out the dependencies so you can focus on the unit you're actually trying to unit test. If all you're doing is zeroing out dependencies, you're not testing much. Every mock you bring in carries and assumption, and those assumptions need to be tested, too.

Cases like that really call for some small scale integration unit tests, where you actually bring in your dependencies and test them all working together.

Re:Warming Up to Unit Testing by derrick_jensen on Monday February 24, 2020 @02:58PM (#22407782)
As a personal rule, I use test versions of the real APIs (or another instance of the API if a testing version isn't provided) on the CICD, and I use stubbed versions locally. Main motivation was that race conditions can happen between the two, and there is only one CICD, but many developers. I change the interfaces through feature flags/macros at compile time

EDIT: What I'm working on currently doesn't have a hardware component to it, so this might not be practical in the future

Re:Warming Up to Unit Testing by fishstamp82 on Monday February 24, 2020 @11:43AM (#22405620)
I think verifying that your code calls this and that is that it actually works the way you expect. Without such test we might assume code works in one way when the happy path is not even reached.

I find it valuable at times, depending on the context, but I agree that extensive mock testing like this can get quite useless real quick.