On Mockito 4, `mock(TaxTable.class)` failed because `TaxTable` is a `final` class; after upgrading to Mockito 5 the same test passes, and a teammate starts using `mockStatic(Instant.class)` to control time. Explain what a Mockito mock is at runtime under each mock maker, why the upgrade changed the result, and what you would say in review about the static mock.
A mock is not a real instance of your class. With the subclass mock maker (the long-time default), Mockito uses ByteBuddy to generate a new class at runtime that extends the target (or implements the interface) and overrides every non-final method to route through a handler that records calls and consults the stubs; Objenesis instantiates it without calling any constructor. A subclass cannot extend a final class or override a final method, so that failure was mechanical, not a policy. Mockito 5 made the inline mock maker the default: it attaches a java.lang.instrument agent and rewrites the target class's own bytecode, which is what makes final classes, final methods and mockStatic possible. In review: mocking Instant statically is working around a missing seam. Inject a Clock and use Clock.fixed(...) in tests.