[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)