Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mockito 2 - The return of the King

Mockito 2 - The return of the King

Probably there is no Java developer in the world who writes tests and haven't heard about Mockito. That most popular mocking framework for Java will be celebrating its 10th birthday soon. However, I don't plan to brood the history. At the end of 2016 the new and shiny Mockito 2 has been released.

During the presentation I will show what brand new features have been implemented in Mockito 2 and what improvements you can expect. We will also take a closer look at the places which changed incompatibly and possible migration pitfalls. You will be able to judge if it was worth to wait almost 2 years since Mockito 1.10.19.

Marcin Zajączkowski

May 18, 2017
Tweet

More Decks by Marcin Zajączkowski

Other Decks in Programming

Transcript

  1. About me Areas of expertise Automatic Testing / TDD Software

    Craftsmanship / Code Quality Concurrency / Parallel Computing / Reactive Systems Deployment Automation / Continuous Delivery FOSS projects author and contributor, including creator of mockito-java8 author of Mockito Refcard (minor) contributor to Mockito itself blogger and trainer Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  2. I'm open to new interesting opportunities as Tool engineer (especially

    related to Continuous Delivery and/or testing in a company where quality matters) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  3. Presentation goal Show new features and changes in Mockito 2

    in an easily digestible 50 minute format Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  4. Presentation plan matchers Java 8 support tests quality internals mocking

    unmockeable common migration issues infrastructure future Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  5. Facts about Mockito most popular mocking framework for Java *

    very mature - started in 2007 by Szczepan Faber industrial standard . Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  6. Facts about Mockito most popular mocking framework for Java *

    very mature - started in 2007 by Szczepan Faber industrial standard . some alternatives exist Spock (with its mocks), JMockit good for people to have choice and to put Mockito development forward :) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  7. Facts about Mockito 2 2.1.0 released in October 2016 first

    stable 2.x version after almost two years since 1.10.19 100+ beta versions in the meantime actively developed by 4 core developers and group of contributors a lot of improvements and new features Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  8. Matchers - implementation separation from Hamcrest matchers no more confusion

    no extra transitive dependency no potential issues with incompatibility between versions new base class org.mockito.ArgumentMatchers Hamcrest matchers still available via MockitoHamcrest.argThat() Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  9. Matchers - behavior "fixed" awkwardness and inconsistency between matchers Marcin

    Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  10. Matchers - behavior "fixed" awkwardness and inconsistency between matchers e.g.

    any(Foo.class) in Mockito 1.x - ? Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  11. Matchers - behavior "fixed" awkwardness and inconsistency between matchers e.g.

    any(Foo.class) in Mockito 1.x - ? no checking if argument is instance of Foo (in 1.x) . Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  12. Matchers - behavior "fixed" awkwardness and inconsistency between matchers e.g.

    any(Foo.class) in Mockito 1.x - ? no checking if argument is instance of Foo (in 1.x) . stronger type checking null values not accepted by default based on internal discussions and feedback from community Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  13. Matchers - behavior in 2.x any() - matches everything (including

    null value) any(Foo.class) - not null object of given type anyList() - not null list isNull() - null instance Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  14. BDDMockito - BDD-like consistent syntax alternative naming convention given..will instead

    of when..then to follow given-when-then test structure @Test public void shouldReturnGivenValueUsingBDDNotation() { //given TacticalStation tacticalStationMock = mock(TacticalStation.class); given(tacticalStationMock.getNumberOfTubes()).willReturn(TEST_NUMBER_OF_TORPEDO_TUBES); //when int numberOfTubes = tacticalStationMock.getNumberOfTubes(); //then assertThat(numberOfTubes).isEqualTo(TEST_NUMBER_OF_TORPEDO_TUBES); } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  15. BDDMockito - BDD-like consistent syntax alternative naming convention given..will instead

    of when..then to follow given-when-then test structure @Test public void shouldReturnGivenValueUsingBDDNotation() { //given TacticalStation tacticalStationMock = mock(TacticalStation.class); given(tacticalStationMock.getNumberOfTubes()).willReturn(TEST_NUMBER_OF_TORPEDO_TUBES); //when int numberOfTubes = tacticalStationMock.getNumberOfTubes(); //then assertThat(numberOfTubes).isEqualTo(TEST_NUMBER_OF_TORPEDO_TUBES); } less known although available since Mockito 1.8.0 Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  16. BDDMockito - new alias for verification then instead of verify

    @Test public void shouldVerifyWithSimpleArgumentMatching() { //given TacticalStation tacticalStationMock = mock(TacticalStation.class); //when tacticalStationMock.fireTorpedo(5); //then then(tacticalStationMock).should().fireTorpedo(gt(3)); // verify(tacticalStationMock).fireTorpedo(gt(3)); } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  17. BDDMockito - new alias for verification then instead of verify

    @Test public void shouldVerifyWithSimpleArgumentMatching() { //given TacticalStation tacticalStationMock = mock(TacticalStation.class); //when tacticalStationMock.fireTorpedo(5); //then then(tacticalStationMock).should().fireTorpedo(gt(3)); // verify(tacticalStationMock).fireTorpedo(gt(3)); } with its counterparts then().should(InOrder inOrder) then().should(InOrder inOrder, VerificationMode mode) then().shouldHaveZeroInteractions() then().shouldHaveNoMoreInteractions() Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  18. BDDMockito - adjustment to "classic" Mockito new/renamed equivalent methods given().willThrow(Class<?

    extends Throwable> throwableType) given().will(Answer<?> answer) given().willReturn(Object toBeReturned, Object... toBeReturnedNext) given().willDoNothing() . to make BDDMockito the first class citizen Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  19. (Preliminary) Java 8 support empty values for unstubbed method returning

    Optional and Stream deprecate matches accepting class as argument just to prevent compiler warning e.g. anyListOf(Class<T>) -> anyList() type inference Java 8 is much better Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  20. (Preliminary) Java 8 support empty values for unstubbed method returning

    Optional and Stream deprecate matches accepting class as argument just to prevent compiler warning e.g. anyListOf(Class<T>) -> anyList() type inference Java 8 is much better ability to call default method in interface in mock by default default methods are stubbed given(someInterfaceMock.defaultMethod()).willCallRealMethod(); Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  21. (Preliminary) Java 8 support - ctd. argument matcher as lambda

    to inline custom matcher creation given(ts.findNumberOfShipsInRangeByCriteria( argThat(c -> c.getMinimumRange() > 1000))).willReturn(4); Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  22. (Preliminary) Java 8 support - ctd. argument matcher as lambda

    to inline custom matcher creation given(ts.findNumberOfShipsInRangeByCriteria( argThat(c -> c.getMinimumRange() > 1000))).willReturn(4); handy way to define answer with lambda expression explicit type definition in lambda is usually required given(ts.findNumberOfShipsInRangeByCriteria(any(ShipSearchCriteria.class))) .willAnswer(AdditionalAnswers.answer( (ShipSearchCriteria criteria) -> criteria.getMinimumRange() > 1000 ? 4 : 0)); Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  23. (Preliminary) Java 8 support - ctd. argument matcher as lambda

    to inline custom matcher creation given(ts.findNumberOfShipsInRangeByCriteria( argThat(c -> c.getMinimumRange() > 1000))).willReturn(4); handy way to define answer with lambda expression explicit type definition in lambda is usually required given(ts.findNumberOfShipsInRangeByCriteria(any(ShipSearchCriteria.class))) .willAnswer(AdditionalAnswers.answer( (ShipSearchCriteria criteria) -> criteria.getMinimumRange() > 1000 ? 4 : 0)); Mockito 2.x works with Java 6+ full Java 8 support in Mockito 3.x Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  24. Lenient stubs Mockito stubs are lenient by default default "neutral"

    value is returned when unstubbed as opposed to EasyMock where not declared invocation fails test convenient to not overspecify test . Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  25. Lenient stubs Mockito stubs are lenient by default default "neutral"

    value is returned when unstubbed as opposed to EasyMock where not declared invocation fails test convenient to not overspecify test . occasionally it may generate hard to diagnose errors especially in too complicated tests Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  26. Issues with wrong stubbing private static final String ENTERPRISE_D =

    "USS Enterprise (NCC-1701-D)"; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Test public void shouldFindOwnShipByName() { //given ShipDatabase shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex); given(ownShipIndex.findByName("Enterpris")).willReturn(singletonList(ENTERPRISE_D)); //when List<String> foundShips = shipDatabase.findByName("Enterprise"); //then assertThat(foundShips).contains(ENTERPRISE_D); } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  27. Issues with wrong stubbing private static final String ENTERPRISE_D =

    "USS Enterprise (NCC-1701-D)"; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Test public void shouldFindOwnShipByName() { //given ShipDatabase shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex); given(ownShipIndex.findByName("Enterpris")).willReturn(singletonList(ENTERPRISE_D)); //when List<String> foundShips = shipDatabase.findByName("Enterprise"); //then assertThat(foundShips).contains(ENTERPRISE_D); } java.lang.AssertionError: Expecting: <[]> to contain: <["USS Enterprise (NCC-1701-D)"]> but could not find: <["USS Enterprise (NCC-1701-D)"]> at StrictStubbingTest.shouldFindOwnShipByName(StrictStubbingTest.java:37) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  28. Issues with wrong stubbing private static final String ENTERPRISE_D =

    "USS Enterprise (NCC-1701-D)"; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Test public void shouldFindOwnShipByName() { //given ShipDatabase shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex); given(ownShipIndex.findByName("Enterpris")).willReturn(singletonList(ENTERPRISE_D)); //when List<String> foundShips = shipDatabase.findByName("Enterprise"); //then assertThat(foundShips).contains(ENTERPRISE_D); } stack trace points to assertThat() line that kind of typo can be hard to spot quickly in larger test Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  29. (Partially) strict stubbing in Mockito 2 detection of mismatched stubbed

    method execution (with no matching parameters) make failing test "debugging" easier by default warning on console but who reads warnings? strict mode on demand Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  30. (Partially) strict stubbing in Mockito 2 @Rule public MockitoRule mockitoRule

    = MockitoJUnit.rule() .strictness(Strictness.STRICT_STUBS); //by default Strictness.WARN @Test public void shouldFindOwnShipByName() { ... } org.mockito.exceptions.misusing.PotentialStubbingProblem: Strict stubbing argument mismatch. Please check: - this invocation of 'findByName' method: ownShipIndex.findByName("Enterprise"); -> at ShipDatabase.findByName(ShipDatabase.java:17) - has following stubbing(s) with different arguments: 1. ownShipIndex.findByName("Enterpris"); -> at StrictStubbingTest.shouldFindOwnShipByName(StrictStubbingTest.java:33) Typically, stubbing argument mismatch indicates user mistake when writing tests. Mockito fails early so that you can debug potential problem easily. However, there are legit scenarios when this exception generates false negative signal: - stubbing the same method multiple times using 'given().will()' or 'when().then()' API Please use 'will().given()' or 'doReturn().when()' API for stubbing. - stubbed method is intentionally invoked with different arguments by code under test Please use 'default' or 'silent' JUnit Rule. For more information see javadoc for PotentialStubbingProblem class. pointing to existing stubbing and production code execution lines Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  31. Soft verification with JUnit rule by default mock invocation verification

    fails on first failure occasionally it can be useful to get full report easy with collector JUnit rule Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  32. MockitoRule and soft verification @Rule public VerificationCollector mockitoRule = MockitoJUnit.collector();

    @Test public void shouldCheckAllVerifications() { //given TacticalStation tsMock = mock(TacticalStation.class); OperationsStation osMock = mock(OperationsStation.class); //and SpaceShip spaceShip = new SpaceShip(tsMock, osMock); //when spaceShip.doSelfCheck(); //missing invocation under the hood //then then(tsMock).should().doSelfCheck(); then(osMock).should().doSelfCheck(); } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  33. MockitoRule and soft verification @Rule public VerificationCollector mockitoRule = MockitoJUnit.collector();

    @Test public void shouldCheckAllVerifications() { //given TacticalStation tsMock = mock(TacticalStation.class); OperationsStation osMock = mock(OperationsStation.class); //and SpaceShip spaceShip = new SpaceShip(tsMock, osMock); //when spaceShip.doSelfCheck(); //missing invocation under the hood //then then(tsMock).should().doSelfCheck(); then(osMock).should().doSelfCheck(); } org.mockito.exceptions.base.MockitoAssertionError: There were multiple verification failures: 1. Wanted but not invoked: tacticalStation.doSelfCheck(); -> at SelfCheckTest.shouldCheckAllVerifications(SelfCheckTest.java:40) Actually, there were zero interactions with this mock. 2. Wanted but not invoked: operationsStation.doSelfCheck(); -> at SelfCheckTest.shouldCheckAllVerifications(SelfCheckTest.java:41) Actually, there were zero interactions with this mock. Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  34. Unneeded stubbing detection easy to stub unnecessary (if not written

    with TDD) especially if test is too big written by newbies powered by copy-paste Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  35. Unneeded stubbing detection @Test public void shouldFindOwnShipByNameAndDetectUnnecessaryStubbing() { //given ShipDatabase

    shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex); willReturn(singletonList(ENTERPRISE_D)).given(ownShipIndex).findByName("Enterprise"); willReturn(singletonList("USS Intrepid")).given(ownShipIndex).findByName("Intrepid"); willReturn(singletonList("USS Defiant")).given(ownShipIndex).findByName("Defiant"); //when List<String> foundShips = shipDatabase.findByName("Enterprise"); //then assertThat(foundShips).contains(ENTERPRISE_D); } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  36. Unneeded stubbing detection @Test public void shouldFindOwnShipByNameAndDetectUnnecessaryStubbing() { //given ShipDatabase

    shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex); willReturn(singletonList(ENTERPRISE_D)).given(ownShipIndex).findByName("Enterprise"); willReturn(singletonList("USS Intrepid")).given(ownShipIndex).findByName("Intrepid"); willReturn(singletonList("USS Defiant")).given(ownShipIndex).findByName("Defiant"); //when List<String> foundShips = shipDatabase.findByName("Enterprise"); //then assertThat(foundShips).contains(ENTERPRISE_D); } org.mockito.exceptions.misusing.UnnecessaryStubbingException: Unnecessary stubbings detected. Clean & maintainable test code requires zero unnecessary code. Following stubbings are unnecessary (click to navigate to relevant line of code): 1. -> at StrictStubbingTest.shouldFindOwnShipByName(StrictStubbingTest.java:45) 2. -> at StrictStubbingTest.shouldFindOwnShipByName(StrictStubbingTest.java:46) Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for ... or stubbing other not important for that test mock Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  37. Unneeded stubbing detection quite often may result in false positives

    still work in progress with limitations willReturn().given() or thenReturn().when() has to be used instead of given().willReturn() or when().thenReturn() Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  38. Strict mode for non JUnit users MockitoSession to emulate JUnit

    rule in TestNG MocitoRule does it for you automatically @Test public abstract class BaseTestNGTest { private MockitoSession mockito; //can be kept in superclass, not needed for JUnit @BeforeMethod public void init() { mockito = Mockito.mockitoSession() .initMocks(this) .strictness(Strictness.STRICT_STUBS) .startMocking(); } @AfterMethod public void tearDown() { mockito.finishMocking(); } ... } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  39. Byte Buddy - cglib replacement new mechanism for byte code

    manipulation actively maintained by Rafael Winterhalter, Mockito core developer fixing some long standing issues/limitations of cglib good Java 8 and 9 support very convenient (fluent) API becoming popular Hibernate, Bazel, Spock, Awaitility, ... Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  40. mockito-all artifact (finally) discontinued legacy stuff with Mockito dependencies put

    together Ant times more popular than mockito-core due to unawareness... mockito-core perfect for modern dependency management tools Gradle, Maven, Sbt, ... Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  41. Native Android support separate submodule - mockito-android class proxy for

    Dalvik VM byte-buddy-android under the hood dependencies { testCompile "org.mockito:mockito-core:${mockitoVersion}" androidTestCompile "org.mockito:mockito-android:${mockitoVersion}" } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  42. Mocking unmockable new (incubating) mocking mechanism combination of both Java

    instrumentation API and sub-classing possible thanks to migration to Byte Buddy mocking of final classes, enums and final methods disabled by default create /mockito-extensions/org.mockito.plugins.MockMaker file on classpath with mock-maker-inline value to turn it on no more changes needed Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  43. Mocking unmockable - limitations not everything can be mocked package-visible

    methods of java.* native methods potential conflicts with other Java agents community feedback needed! Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  44. Mocking builders public class ShipSearchCriteriaBuilder { public ShipSearchCriteriaBuilder withMinimumRange(int minimumRange)

    { ... } public ShipSearchCriteriaBuilder withNumberOfPhasers(int numberOfPhasers) { ... } ... public ShipSearchCriteria build() { ... } } chained execution of methods returning self (this) risk of NPE if only build method is stubbed Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  45. Mocking builders public class ShipSearchCriteriaBuilder { public ShipSearchCriteriaBuilder withMinimumRange(int minimumRange)

    { ... } public ShipSearchCriteriaBuilder withNumberOfPhasers(int numberOfPhasers) { ... } ... public ShipSearchCriteria build() { ... } } chained execution of methods returning self (this) risk of NPE if only build method is stubbed mock(ShipSearchCriteriaBuilder.class, Mockito.RETURNS_SELF); automatic stubbing builder methods returning self mock itself returned (for matching return type) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  46. Common migration issues matchers package in (static) imports org.mockito.Matchers.anyLong ->

    org.mockito.ArgumentMatchers.anyLong passed argument type checking e.g. anyList() and anyCollection() null argument not allowed in most cases isNull() to check it explicitly Hamcrest matchers Matchers.argThat() -> MockitoHamcrest.argThat() Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  47. Common migration issues - ctd. mockito-all -> mockito-core if -all

    accidentally used before Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  48. Common migration issues - ctd. mockito-all -> mockito-core if -all

    accidentally used before internal stuff - partially changed or removed PowerMock initial version with Mockito 2 support in March 2017 direct usage in tests Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  49. Continuous Delivery Continuous Delivery implemented in Mockito years ago artifacts

    deployed from Travis to The Central Repository (aka Maven Central) and JCenter release notes generation based on issues and PRs in GitHub new feature available as non snapshot version minutes after merge to master Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  50. Continuous Delivery Continuous Delivery implemented in Mockito years ago artifacts

    deployed from Travis to The Central Repository (aka Maven Central) and JCenter release notes generation based on issues and PRs in GitHub new feature available as non snapshot version minutes after merge to master 100+ beta versions of 2.0/2.1 occasionally more than one version a day some people didn't like it Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  51. Mockito Continuous Delivery Pipeline 2.0 every new version deployed only

    to mockito-development Bintray repository artifacts available only if explicitly configured in end project only versions with notable changes deployed to The Central Repository and JCenter based on labels in issue tracker developers can choose frequency of update Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  52. Future plans - Mockito 3 comprehensive Java 8 support Java

    8 as minimal supported version simplified internal implementation new stubbing syntax default methods in interface to eliminate static imports currently available as separate add-on - mockito-java8 declared Java 9 compatibility no rush for that in the team new features still added in (default) 2.x branch Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  53. Summary - Mockito 2 set of nice new features to

    help you write better and more readable tests Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  54. Summary - Mockito 2 set of nice new features to

    help you write better and more readable tests migration is doable in sensible time unless you use PowerMock or Mockito internals directly Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  55. Summary - Mockito 2 set of nice new features to

    help you write better and more readable tests migration is doable in sensible time unless you use PowerMock or Mockito internals directly expect even more in the future :-) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  56. Thank you! (and remember about the feedback) Marcin Zajączkowski http://blog.solidsoft.info/

    @SolidSoftBlog [email protected] Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/