29 comments

  • pron 3 minutes ago

    > 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 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.

    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.

    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 but only if the application is made aware of it and allows is. What isn't allowed is for a library - which could be some fourth-level dependency - to decide for itself, without the application's knowledge, that actually strings 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 minimise 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 - wasn't really a solid foundation, but it is now: https://youtu.be/AzfhxgkBL9s?t=1843.

  • CodesInChaos 25 minutes ago

    What does Agent mean in this context? And what is "dynamic attachment of agents"?

      njitbew 13 minutes ago

      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.

      LoganDark 15 minutes ago

      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.

  • senko an hour ago

    For those, like me, who haven't heard of it: Mockito is the "most popular mocking framework for Java".

      ronnier an hour ago

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

        nsxwolf a few seconds ago

        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.

      schumpeter an hour ago

      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 42 minutes ago

        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 28 minutes ago

          >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 30 minutes ago

        Actually, no. "small booger" would be _moquito_ in spanish.

          schumpeter 4 minutes ago

          Fair. The spelling is off, but the pronunciation is the same.

  • krackers an hour ago

    >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 an hour ago

    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 32 minutes ago

      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.

  • didip an hour ago

    As someone who is not in the Java world, why does Java need a mocking library? Interface based polymorphism is not enough?

      krackers an hour ago

      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 37 minutes ago

        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 35 minutes ago

          your test environment should not have the credentials to write to prod data. yiiiiikes!

            sunnybeetroot 32 minutes ago

            Credentials end up existing in prod because the person used Mochito and didn’t override the function for providing credentials :’c

      tripple6 an hour ago

      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 21 minutes ago

      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.

      totallykvothe an hour ago

      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 27 minutes ago

        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.

      marginalia_nu an hour ago

      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.

      eoskx an hour ago

      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.

      gleenn an hour ago

      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.

      voidhorse an hour ago

      Arguably it doesn't. Mocking is over used and you should just use a real implementation or distributor provided fake whenever possible.

  • gleenn an hour ago

    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.