Live data from Hacker News

Stepping down as Mockito maintainer after ten years

github.com

91–100 of 220 posts

Re: Stepping down as Mockito maintainer after ten years

#91
post #32
post #3

Earlier quoted context omitted.

It’s taken years off of my life dealing with the test mess people have made with it.

Absolutely the worst. 1000 line test setups that shatter into pieces the instant you try to make the simplest change to a function. Makes refactoring an absolute nightmare.

Which is absurd that people use mocks considering the tests are supposed to help with refactoring but because of the mocks they can’t make a change without breaking the test.

Re: Stepping down as Mockito maintainer after ten years

#93

Earlier quoted context omitted.

The whole mocks, fakes and the rest were always a terrible idea. Although people didn't realize it st the time, they were a band-aid to try to make poorly architected code testable. 90% of the time, needing to use a mock is one of the clearest code warning smells you have of there being an issue in the design your code. It took a while, but the industry seems to be finally (although slowly) coming to this realization…

How do you substitute for dependencies that you're not testing, or that you want to deliberately break?

Why substitute dependencies? Is the isolation worth it?

Re: Stepping down as Mockito maintainer after ten years

#94

This is a good opportunity to ditch mocking and use fakes with adapters. Not only mocks create brittle tests that often test only the framework itself, but they do so in an order of magnitude slower way. Also, F Kotlin and their approach of "we'll reinvent the wheel with slightly different syntax and call it a new thing". Good riddance I say, let them implement their mockk, or whatever it is called, with ridiculous "…

The whole mocks, fakes and the rest were always a terrible idea. Although people didn't realize it st the time, they were a band-aid to try to make poorly architected code testable. 90% of the time, needing to use a mock is one of the clearest code warning smells you have of there being an issue in the design your code. It took a while, but the industry seems to be finally (although slowly) coming to this realization…

I agree. Tests relying on mocks rarely uncover or prevent issues. They also typically make it harder to make changes. Very bad idea that should have been left behind years ago.

Re: Stepping down as Mockito maintainer after ten years

#95
post #80

Wow, there's a lot of anger in some of these posts. I've been using Mockito for about 4 years, all in Kotlin. I always found it to be "plenty good" for like 99% of the cases I needed it; and things more complicated or confusing or messy were usually my fault (poor separation of concerns, etc). I regularly found it quite helpful in both its spy() and mock() functionality. I never found it meaningfully more or less use…

Is it anger? The agent thing maybe. The other two points seem to boil down to: 1. Kotlin is a hack and 2. Rust is more fun. Pretty understandable why one would simply want to move on to greener pastures.

I'm not sure Kotlin is a hack, but it's growth is directly related to Java not being able to deliver on simple features that would help the day to day lives of developers. So I also can't blame anyone for moving on from the language. I get frustrated with it all the time, especially when Kotlin shows that some feature could work perfectly fine.

Here are some examples that have hit the graveyard: It's been 2 years since exception handling in switch was proposed [0], 3 years since null-restricted types were proposed [1], 4 years since string templates [2], 8 years since concise method bodies [3], and 11 years for JSON parsing [4].

[0] https://inside.java/2023/12/15/switch-case-effect/

[1] https://openjdk.org/jeps/8303099

[2] https://openjdk.org/jeps/430

[3] https://openjdk.org/jeps/8209434

[4] https://openjdk.org/jeps/198

Re: Stepping down as Mockito maintainer after ten years

#96
post #77

My second project at Google basically killed mocking for me and I've basically never done it since. Two things happened. The first was that I worked on a rewrite of something (using GWT no less; it was more than a decade ago) and they decided to have a lot of test coverage and test requirements. That's fine but they way it was mandated and implemented, everybody just testing their service and DIed a bunch of mocks in…

“The solution is to have dummy versions of services and interfaces that have minimal correct behavior” If you aren’t doing this with mocks then you’re doing mocks wrong.

In part, you’re right, but there’s a practical difference between mocking and a good dummy version of a service. Take DynamoDB local as an example: you can insert items and they persist, delete items, delete tables, etc. Or in the Ruby on Rails world, one often would use SQLite as a local database for tests even if using a different DB in production.

Going further, there’s the whole test containers movement of having a real version of your dependency present for your tests. Of course, in a microservices world, bringing up the whole network of dependencies is extremely complicated and likely not warranted.

Re: Stepping down as Mockito maintainer after ten years

#97
post #68
post #61

Earlier quoted context omitted.

IMO Mockito is fine, the problem I’ve encountered is people taking the easy way out and trying to test something that needs a real integration test with a convoluted series of mocks.

I've found that most of the time that if you need to mock, you probably just need to do an integration test.

I can’t concur with this enough.

I’ve been on projects where mocking _literally made the project less reliable_ because people ended up “testing” against mocks that didn’t accurately reflect the behavior of the real APIs.

It left us with functionality that wasn’t actually tested and resulted in real bugs and regressions that shipped.

Mocking is one of these weird programmer pop-culture memetic viruses that spread in the early 2000s and achieved complete victory in the 2010s, like Agile and OOP, and now there are entire generations of devs who it’s not that they’re making a bad or a poorly argued choice, it’s that they literally don’t even know there are other ways of thinking about these problems because these ideas have sucked all the oxygen out of the room.

Re: Stepping down as Mockito maintainer after ten years

#98
post #77

My second project at Google basically killed mocking for me and I've basically never done it since. Two things happened. The first was that I worked on a rewrite of something (using GWT no less; it was more than a decade ago) and they decided to have a lot of test coverage and test requirements. That's fine but they way it was mandated and implemented, everybody just testing their service and DIed a bunch of mocks in…

“The solution is to have dummy versions of services and interfaces that have minimal correct behavior” If you aren’t doing this with mocks then you’re doing mocks wrong.

I'd go a bit farther — "mock" is basically the name for those dummy versions.

That said, there is a massive difference between writing mocks and using a mocking library like Mockito — just like there is a difference between using dependency injection and building your application around a DI framework.

Re: Stepping down as Mockito maintainer after ten years

#99
post #77

My second project at Google basically killed mocking for me and I've basically never done it since. Two things happened. The first was that I worked on a rewrite of something (using GWT no less; it was more than a decade ago) and they decided to have a lot of test coverage and test requirements. That's fine but they way it was mandated and implemented, everybody just testing their service and DIed a bunch of mocks in…

“The solution is to have dummy versions of services and interfaces that have minimal correct behavior” If you aren’t doing this with mocks then you’re doing mocks wrong.

The difference, IMO, between a mock and a proper "test" implementation is that traditionally a mock only exists to test interface boundaries, and the "implementation" is meant to be as much of a noop as possible. That's why the default behavior of almost any "automock" is to implement an interface by doing nothing and returning nothing (or perhaps default-initialized values) and provide tools for just tacking assertions onto it. If it was a proper implementation that just happened to be in-memory, it wouldn't really be a "mock", in my opinion.

For example, let's say you want to test that some handler is properly adding data to a cache. IMO the traditional mock approach that is supported by mocking libraries is to go take your RedisCache implementation and create a dummy that does nothing, then add assertions that say, the `set` method gets called with some set of arguments. You can add return values to the mock too, but I think this is mainly meant to be in service of just making the code run and not actually implementing anything.

Meanwhile, you could always make a minimal "test" implementation (I think these are sometimes called "fakes", traditionally, though I think this nomenclature is even more confusing) of your Cache interface that actually does behave like an in-memory cache, then your test could assert as to its contents. Doing this doesn't require a "mocking" library, and in this case, what you're making is not really a "mock" - it is, in fact, a full implementation of the interface, that you could use outside of tests (e.g. in a development server.) I think this can be a pretty good middle ground in some scenarios, especially since it plays along well with in-process tools like fake clocks/timers in languages like Go and JavaScript.

Despite the pitfalls, I mostly prefer to just use the actual implementations where possible, and for this I like testcontainers. Most webserver projects I write/work on naturally require a container runtime for development for other reasons, and testcontainers is glue that can use that existing container runtime setup (be it Docker or Podman) to pretty rapidly bootstrap test or dev service dependencies on-demand. With a little bit of manual effort, you can make it so that your normal test runner (e.g. `go test ./...`) can run tests normally, and automatically skip anything that requires a real service dependency in the event that there is no Docker socket available. (Though obviously, in a real setup, you'd also want a way to force the tests to be enabled, so that you can hopefully avoid an oopsie where CI isn't actually running your tests due to a regression.)

Re: Stepping down as Mockito maintainer after ten years

#100
post #70

Earlier quoted context omitted.

How do you substitute for dependencies that you're not testing, or that you want to deliberately break?

90% of the time (or more): you don't. The real thing is perfectly fine in a test with the right setup. Fileio is fast, I just need a test file in a tempdir. databases are fast, I just need an easy way to settup my schema. Sometimes I need the isolation but normally I do not.

I worked on a project where a dev wanted to mock out the database in tests "for performance, because the database is slow". I almost lost my shit.

Even funnier, this was all hypothetical and yet taken as gospel. We hadn't even written the tests yet, so it was impossible to say whether they were slow or not. Nothing had been measured, no performance budget had been defined, no prototype of the supposedly slow tests had been written to demonstrate the point.

We ended up writing - no joke - less than 100 tests total, almost all of which hit the database, including some full integration tests, and the entire test suite finished in a few seconds.

I'm all for building in a way that respects performance as an engineering value, but we got lost somewhere along the way.

Post reply on HN