[HN Gopher] Stepping down as Mockito maintainer after 10 years
___________________________________________________________________
Stepping down as Mockito maintainer after 10 years
Author : saikatsg
Score : 137 points
Date : 2025-12-28 20:14 UTC (2 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| senko wrote:
| For those, like me, who haven't heard of it: Mockito is the "most
| popular mocking framework for Java".
| ronnier wrote:
| It's taken years off of my life dealing with the test mess
| people have made with it.
| nsxwolf wrote:
| 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.
| pjc50 wrote:
| What's specifically bad about Mockito here? Poor defaults
| for mocks?
| eastbound wrote:
| I'll answer: Nothing specific to Mockito, it happens in
| every language. Tests "solidify" code which makes
| refactoring hard. And yet, after refactoring, one can be
| happy to have tests to check whether there is any
| regression.
|
| Testing is hard. I've tried with AI today: No, it is
| still not capable of handling that kind of
| (straightforward) task (Using Claude).
| blandflakes wrote:
| They also encourage/enable code that is less testable. If
| you use mockito to get your fake responses/assertions
| where you need them, you don't have to think about your
| class's dependencies to make your code testable and
| therefore better decomposed. I don't even _do_ TDD, but I
| still find that thinking about how I 'd test a class
| guides me toward better-factored code.
| t-writescode wrote:
| One alternative to make code with typing styles in the
| Java way (as opposed to the Typescript or Go way) is to
| have a whole lot of custom interfaces and then you end up
| with a whole bunch of: doTheThing(foo:
| Fooable) { ... }
|
| when there's really only one Foo implementation in prod.
| It leads to (what feels like, to me) more code
| obfuscation in large projects, than the benefits that
| come out, at least for me.
|
| So Mockito and friends are a nice alternative to that.
|
| That is _just my experience and opinion_ though, and
| there are definitely more valid or equally valid
| alternatives.
| schumpeter wrote:
| It also translates to "small booger", in Spanish, which always
| made me question who thought the name was a good idea over
| there.
| Freak_NL wrote:
| Why? Every name you pick is likely to be weird in one
| language or another. Mockito does one thing well as a name,
| and that is hinting strongly at what it is (a mocking
| library).
| kace91 wrote:
| >is likely to be weird in one language or another.
|
| But this name is weird in the specific language it's
| imitating (both the -ito termination for diminutives and
| the drink on which I assumed the name is based are
| Spanish).
| marinesebastian wrote:
| Actually, no. "small booger" would be _moquito_ in spanish.
| schumpeter wrote:
| Fair. The spelling is off, but the pronunciation is the
| same.
| kaoD wrote:
| I'm Spanish and subconsciously pronounced the library as
| MOCKito, as opposed to moQUIto.
| dhosek wrote:
| I'm bilingual(ish) and while I've always pronounced it
| MOCKito, I think I may start pronouncing it moQUIto
| instead now.
| awesome_dude wrote:
| Look, as an English only speaker I don't care - I'm still
| stuck at "Haw haw, small booger library!"
| didip wrote:
| As someone who is not in the Java world, why does Java need a
| mocking library? Interface based polymorphism is not enough?
| voidhorse wrote:
| Arguably it doesn't. Mocking is over used and you should just
| use a real implementation or distributor provided fake whenever
| possible.
| totallykvothe wrote:
| Mockito allows one to write mocks in tests for code that
| doesn't use dependency injection and isn't properly testable in
| any other way.
|
| On the one hand, you should just design things to be testable
| from the start. On the other... I'm already working in this
| codebase with 20 years of legacy untestable design...
| deepsun wrote:
| Google API libraries mark every class as "final" so it's not
| trivial to mock-extend it for tests. But third-party IO is
| exactly the thing you'd want to mock.
|
| Probably because they zealously followed "Effective Java"
| book.
| wiseowise wrote:
| > But third-party IO is exactly the thing you'd want to
| mock.
|
| You write an adapter.
| deepsun wrote:
| No, some other library classes accept only their own, not
| my adapter.
|
| Not mentioning of course needless copy-pasting dosens of
| members in the adapter. And it must be in prod code, not
| tests, even though it's documentation would say "Adapter
| for X, exists only for tests, to be able to mock X".
| gleenn wrote:
| There are many cases where you don't control the library code
| your code depends on that you want to test. Also, the
| FactoryFactoryFactory patterns can be quite cumbersome and
| simply mocking out something makes for a far simpler test.
| There are likely more common cases.
| eoskx wrote:
| As someone who has been out of Java for close to 10 years now,
| you certainly could do without Mockito, but you'd be writing a
| lot of boiler plate code repetitively. There's also the case of
| third-party libraries that you don't control and Mockito has
| decent facilities for working with those, especially when
| you're working with a codebase that isn't pure DI and
| interfaces.
| marginalia_nu wrote:
| The point is to let you create mocks _without_ having to go
| through the whole polymorphism rigmarole, without forcing
| classes to define a separate interface or anything like that.
| krackers wrote:
| Mocks make it easy to record and assert on method invocations.
| Additionally spys (instance mocks) are really useful when you
| need to forward to the real method or rely on some state.
|
| At the moment I can't see anything Mokckito gives that you
| technically couldn't implement yourself via subclassing and
| overriding, but it'd be a lot of boilerplate to proxy things
| and record the arguments.
| sunnybeetroot wrote:
| Subclasing and overriding is not a good idea. There is no
| compilation failure if you forget to override a function
| which can lead to flakey tests at best and prod data impact
| at worst.
| wmichelin wrote:
| your test environment should not have the credentials to
| write to prod data. yiiiiikes!
| sunnybeetroot wrote:
| Credentials end up existing in prod because the person
| used Mochito and didn't override the function for
| providing credentials :'c
| senbrow wrote:
| Credentials should only be provided at the application
| root, which is going to be a different root for a test
| harness.
|
| Mockito shouldn't change whether or not this is possible;
| the code shouldn't have the prod creds (or any external
| resource references) hard coded in the compiled bytecode.
| sunnybeetroot wrote:
| I totally agree, I'm being tongue in cheek, but given how
| poor some codebases can be, the more precautions the
| better ie compilation failures on non-mocked functions.
| tripple6 wrote:
| Mockito uses declarative matching style of specifying what
| should be mocked. You don't need to implement or even stub all
| of interface methods since Mockito can do it itself. It may be
| extremely concise. For example, interfaces may have tens
| methods or even more, but only one method is needed (say,
| java.sql.ResultSet). And finally probably the most important
| thing, interaction with mocks is recorded and then can be
| verified if certain methods were invoked with certain
| arguments.
| davnicwil wrote:
| because even supposing you have an interface for your thing
| under test (which you don't necessarily, nor do you necessarily
| want to have to) it lets you skip over having to do any fake
| implementations, have loads of variations of said fake
| implementations, have that code live somewhere, etc etc.
|
| Instead your mocks are all just inline in the test code:
| ephemeral, basically declarative therefore readily readable &
| grokable without too much diversion, and easily changed.
|
| A really good usecase for Java's 'Reflection' feature.
| BlackFly wrote:
| An anonymous inner class is also ephemeral, declarative,
| inline, capable of extending as well as implementing, and
| readily readable. What it isn't is terse.
|
| Mocking's killer feature is the ability to partially
| implement/extend by having some default that makes some sense
| in a testing situation and is easily instantiable without
| calling a super constructor.
|
| Magicmock in python is the single best mocking library
| though, too many times have I really wanted mockito to also
| default to returning a mock instead of null.
| wiseowise wrote:
| It doesn't. But good luck teaching hordes of enterprise
| "developers".
| throwaway7375 wrote:
| Before Mockito, it was common (where I worked) to create an
| interface just to support testing. This is an anti-pattern in
| my opinion. To create interfaces just for testing just
| complicates the code.
|
| I prefer Mockito's approach.
| gleenn wrote:
| Sad to see an important project's core maintainer leave but their
| justification seems very understandable. It is sad so much of OSS
| is maintained by very few as they alluded to in the XKCD comment,
| an especially given they felt the JVM ecosystem was causing them
| pain with limited support or feedback possible. I think it is
| always a little irresponsible to cause a great deal of breakage
| and not be there to support those who you break downstream of
| your project.
| krackers wrote:
| >Mockito 5 shipped a breaking change where its main artifact is
| now an agent. That's because starting JVM 22, the previous so-
| called "dynamic attachment of agents" is put behind a flag
|
| Wouldn't this hold back enterprise adoption, the same way
| breaking changes meant that Java 8 was widely used for a long
| time?
| njitbew wrote:
| I respect the maintainer's decision, but I don't understand the
| justification.
|
| > but when it was communicated with Mockito I perceived it as
| "Mockito is holding the JVM ecosystem back by using dynamic
| attachment, please switch immediately and figure it out on your
| own".
|
| Who did the communication? Why is dynamic attachment through a
| flag a problem, and what was the solution? Why is "enable a flag
| when running tests" not a satisfactory solution? Why do you even
| need a _dynamic_ agent; don't you know ahead of time exactly what
| agent you need when using Mockito?
|
| > While I fully understand the reasons that developers enjoy the
| feature richness of Kotlin as a programming language, its
| underlying implementation has significant downsides for projects
| like Mockito. Quite frankly, it's not fun to deal with.
|
| Why support Kotlin in the first place? If it's a pain to deal
| with, perhaps the Kotlin user base is better served by a Kotlin-
| specific mocking framework, maintained by people who enjoy
| working on those Kotlin-specific code paths?
| moribvndvs wrote:
| Mockito was indeed a poor fit for Kotlin. MockK is the one.
| Except I suppose for shops that have projects that mix Java and
| Kotlin and already have a Mockito tests.
| CodesInChaos wrote:
| What does Agent mean in this context? And what is "dynamic
| attachment of agents"?
| LoganDark wrote:
| A JVM agent is able to instrument and modify running JVM
| applications. Stuff like debugging, hot patching, etc rely on
| this. You used to be able to tell the JVM to listen on a port
| where you could connect debuggers (agents) dynamically at
| runtime, but that was deemed a security issue so now you can
| only declare specific agents at launch time through command-
| line flags.
| njitbew wrote:
| See https://openjdk.org/jeps/451: JEP 451: Prepare to Disallow
| the Dynamic Loading of Agents, which has a lot of background on
| the topic.
| michaelt wrote:
| Tools for profiling, debugging, monitoring, thread analysis,
| and test coverage analysis can attach to the Java Virtual
| Machine (JVM) using the 'Tool Interface'
|
| If you've got a running java process on your local machine
| right now, you can use 'jconsole' to see the stack traces of
| all threads, inspect various memory statistics, trigger an
| immediate garbage collection or heap dump, and so on. And of
| course, if the tool is an instrumenting profiler - it needs the
| power to modify the running code, to insert its
| instrumentation. Obviously you need certain permissions on the
| host to do this - just like attaching gdb to a running process.
|
| This capability is used not just by for profiling, debugging
| and instrumentation but also by mockito to do its thing.
|
| Java 21 introduced a warning [1] saying this will be disabled
| in a forthcoming version, unless the process is started with
| '-XX:+EnableDynamicAgentLoading' - whereas previously it was
| enabled by default and '-XX:+DisableAttachMechanism' was used
| to disable it.
|
| The goal of doing this is "platform integrity" - preventing the
| attachment of debugging tools is useful in applications like
| DRM.
|
| [1] https://openjdk.org/jeps/451
| pron wrote:
| > To me, it felt like the feature was presented as a done deal
| because of security.
|
| Not security, but integrity, although security (which is the #1
| concern of companies relying on a platform responsible for
| trillions of dollars) is certainly one of the primary motivations
| for integrity (others being performance, backward compatibility
| or "evolvability", and correctness). Integrity is the ability of
| code to locally declare its reliance on some invariant - e.g.
| that a certain class must not be extended, that a method can only
| be called by other methods in the same class, or that a field
| cannot be reassigned after being assigned in the constructor -
| and have the platform guarantee that the invariant is preserved
| globally throughout the lifetime of the program, no matter what
| other code does. What we call "memory safety" is an example of
| some invariants that have integrity.
|
| This is obviously important for security as it significantly
| reduces the blast radius of a vulnerability (some attacks that
| can be done in JS or Python cannot be done in Java), but it's
| also important for performance, as the compiler needs to know
| that certain optimisations preserve meaning. E.g. strings cannot
| be constant-folded if they can't be relied upon to be truly
| immutable. It's also important for backward-compatibility or
| "evolvability", as libraries cannot depend on internals that are
| not explicitly exposed as public APIs; libraries doing that was
| the cause of the migration pain from Java 8 to 9+, as lots of
| libraries depended on internal, non-API methods that have changed
| when the JDK's evolution started picking up steam.
|
| In Java, we've adopted a policy we call Integrity by Default
| (https://openjdk.org/jeps/8305968), which means that code in one
| component can violate invariants established by code in another
| component _only if the application is made aware of it and allows
| it_. What isn 't allowed is for a library - which could be some
| fourth-level dependency - to decide for itself, without the
| application's knowledge, and at some point during the program's
| execution, that actually strings in this program should be
| mutable. We were, and are, open to any ideas as long as this
| principle is preserved.
|
| Authors of components that do want to do such things find the
| policy inconvenient because their consumers need to do something
| extra that isn't required when using normal libraries. But this
| is a classic case of different users having conflicting
| requirements. No matter what you do, someone will be
| inconvenienced. We, the maintainers of the JDK, have opted for a
| solution that we believe minimises the pain and risk overall,
| when integrated over all users: Integrity is on by default, and
| components that wish to break it need an explicit configuration
| option to allow that.
|
| > built on a solid foundation with ByteBuddy
|
| ByteBuddy's author acknowledges that at least some aspects of
| ByteBuddy - and in particular the self-loading agent that Mockito
| used - weren't really a solid foundation, but now it should be:
| https://youtu.be/AzfhxgkBL9s?t=1843. We are grateful to Rafael
| for explaining his needs to us so that we could find a way to
| satisfy them without violating Integrity by Default.
| 0x1ceb00da wrote:
| > some attacks that can be done in JS or Python cannot be done
| in Java
|
| Examples?
| pron wrote:
| In September there was a supply-chain attack on NPM where the
| payload code injected hooks into the DOM API. Changing the
| behaviour of encapsulated components, like Java's standard
| library, is not possible now without the application
| explicitly allowing code to break the integrity of the
| encapsulated component.
| leapis wrote:
| Is there a point at which library maintainer feedback would
| meaningfully influence a by-default JVM change?
|
| I keep a large production Java codebase and its deployments up-
| to-date. Short of upstreaming fixes to every major dependency,
| the only feasible way to continue upgrading JDK versions has
| often been to carry explicit exceptions to new defaults.
|
| JPMS is a good example: --add-opens was required for many
| applications for a long time, and while there has been real
| progress (e.g. Arrow), it remains necessary today for widely
| deployed infrastructure such as Hadoop, Spark, and Netty.
|
| If widely used testing and instrumentation libraries like
| Mockito are unable to offer a viable alternative in response to
| JEP 451, my response would be to re-enable dynamic agent
| attachment rather than re-architect large, long-lived test
| suites. I can't speak for others, but if this reaction holds
| broadly it would seem to defeat the point of by-default
| changes.
| wiseowise wrote:
| 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 "fluent" syntax.
| t-writescode wrote:
| 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 useful than MockK,
| though I have heard MockK is the "one that's better for Kotlin".
| It's mostly just vocabulary changes for me, the user.
|
| I'm going to have to monitor Mockito's future and see if I'll
| need to swap to MockK at some point if Mockito becomes
| unmaintained.
___________________________________________________________________
(page generated 2025-12-28 23:00 UTC)