Posts Tagged ‘util’

Mockito-Java8 is a set of Mockito add-ons leveraging Java 8 and lambda expressions to make mocking with Mockito even more compact.

At the beginning of 2015 I gave my flash talk Java 8 brings power to testing! at GeeCON TDD 2015 and DevConf.cz 2015. In my speech using 4 examples I showed how Java 8 – namely lambda expressions – can simplify testing tools and testing in general. One of those tools was Mokcito. To not let my PoC code die on slides and to make it simply available for others I have released a small project with two, useful in specified case, Java 8 add-ons for Mockito.

Mockito logo

Quick introduction

As a prerequisite, let’s assume we have the following data structure:

@Immutable
class ShipSearchCriteria {
    int minimumRange;
    int numberOfPhasers;
}

The library provides two add-ons:

Lambda matcher – allows to define matcher logic within a lambda expression.

given(ts.findNumberOfShipsInRangeByCriteria(
    argLambda(sc -> sc.getMinimumRange() > 1000))).willReturn(4);

Argument Captor – Java 8 edition – allows to use ArgumentCaptor in a one line (here with AssertJ):

verify(ts).findNumberOfShipsInRangeByCriteria(
    assertArg(sc -> assertThat(sc.getMinimumRange()).isLessThan(2000)));

Lambda matcher

With a help of the static method argLambda a lambda matcher instance is created which can be used to define matcher logic within a lambda expression (here for stubbing). It could be especially useful when working with complex classes pass as an argument.

@Test
public void shouldAllowToUseLambdaInStubbing() {
    //given
    given(ts.findNumberOfShipsInRangeByCriteria(
        argLambda(sc -> sc.getMinimumRange() > 1000))).willReturn(4);
    //expect
    assertThat(ts.findNumberOfShipsInRangeByCriteria(
        new ShipSearchCriteria(1500, 2))).isEqualTo(4);
    //expect
    assertThat(ts.findNumberOfShipsInRangeByCriteria(
        new ShipSearchCriteria(700, 2))).isEqualTo(0);
}

In comparison the same logic implemented with a custom Answer in Java 7:

@Test
public void stubbingWithCustomAsnwerShouldBeLonger() {  //old way
    //given
    given(ts.findNumberOfShipsInRangeByCriteria(any())).willAnswer(new Answer<Integer>() {
        @Override
        public Integer answer(InvocationOnMock invocation) throws Throwable {
            Object[] args = invocation.getArguments();
            ShipSearchCriteria criteria = (ShipSearchCriteria) args[0];
            if (criteria.getMinimumRange() > 1000) {
                return 4;
            } else {
                return 0;
            }
        }
    });
    //expect
    assertThat(ts.findNumberOfShipsInRangeByCriteria(
        new ShipSearchCriteria(1500, 2))).isEqualTo(4);
    //expect
    assertThat(ts.findNumberOfShipsInRangeByCriteria(
        new ShipSearchCriteria(700, 2))).isEqualTo(0);
}

Even Java 8 and less readable constructions don’t help too much:

@Test
public void stubbingWithCustomAsnwerShouldBeLongerEvenAsLambda() {  //old way
    //given
    given(ts.findNumberOfShipsInRangeByCriteria(any())).willAnswer(invocation -> {
        ShipSearchCriteria criteria = (ShipSearchCriteria) invocation.getArguments()[0];
        return criteria.getMinimumRange() > 1000 ? 4 : 0;
    });
    //expect
    assertThat(ts.findNumberOfShipsInRangeByCriteria(
        new ShipSearchCriteria(1500, 2))).isEqualTo(4);
    //expect
    assertThat(ts.findNumberOfShipsInRangeByCriteria(
        new ShipSearchCriteria(700, 2))).isEqualTo(0);
}

Argument Captor – Java 8 edition

A static method assertArg creates an argument matcher which implementation internally uses ArgumentMatcher with an assertion provided in a lambda expression. The example below uses AssertJ to provide meaningful error message, but any assertions (like native from TestNG or JUnit) could be used (if really needed). This allows to have inlined ArgumentCaptor:

@Test
public void shouldAllowToUseAssertionInLambda() {
    //when
    ts.findNumberOfShipsInRangeByCriteria(searchCriteria);
    //then
    verify(ts).findNumberOfShipsInRangeByCriteria(
        assertArg(sc -> assertThat(sc.getMinimumRange()).isLessThan(2000)));
}

In comparison to 3 lines in the classic way:

@Test
public void shouldAllowToUseArgumentCaptorInClassicWay() {  //old way
    //when
    ts.findNumberOfShipsInRangeByCriteria(searchCriteria);
    //then
    ArgumentCaptor<ShipSearchCriteria> captor = 
        ArgumentCaptor.forClass(ShipSearchCriteria.class);
    verify(ts).findNumberOfShipsInRangeByCriteria(captor.capture());
    assertThat(captor.getValue().getMinimumRange()).isLessThan(2000);
}

Summary

The presented add-ons were created as PoC for my conference speech, but should be fully functional and potentially useful in the specific cases. To use it in your project it is enough to use Mockito 1.10.x or 2.0.x-beta, add mockito-java8 as a dependency and of course compile your project with Java 8+.

More details are available on the project webpage: https://github.com/szpak/mockito-java8

Update 20151217. You may be also interested in my new blog post about using Mockito wihtout static imports.

Advertisements

Looking for a way to use mutation testing and PIT with your Gradle-based project? Your search is over. Recently released gradle-pitest-plugin makes it possible in a very comfortable way.

In short the idea with mutation testing is to modify the production code (introduce mutations) which should change its behavior (produce different results) and cause unit tests to fail. The lack of the failure may indicate that given part of the production code was not covered good enough by the tests. To read more about mutation testing take a look on my previous post or PIT webpage directly.

To start using PIT add following configuration to a build.gradle file in your project:

buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
        //Needed to use a plugin JAR uploaded to GitHub (not available in a Maven repository)
        add(new org.apache.ivy.plugins.resolver.URLResolver()) {
            name = 'GitHub'
            addArtifactPattern 'http://cloud.github.com/downloads/szpak/[module]/[module]-[revision].[ext]'
        }
    }
    dependencies {
        classpath 'info.solidsoft.gradle.pitest:gradle-pitest-plugin:0.28.0'
        classpath 'org.pitest:pitest:0.28'
    }
}

This will add required dependencies to a build script together with a proper repositories configuration.

The second thing is to configure plugin itself.

pitest {
    targetClasses = ['our.base.package.*']
    threads = 4
}

The only required parameter is “targetClasses” – a package containing a code which should be mutated (usually the base package for your project), but in case your tests are written in a thread safe manner I encourage your to give a “threads” parameter a try. It can decrease a time required for mutation analysis dramatically. gradle-pitest-plugin supports all reasonable parameters available in PIT.

Having everything configured running mutation testing is as easy as:

gradle pitest

After a while you should see PIT summary similar to:

================================================================================
- Statistics
================================================================================
Generated 59 mutations Killed 52 (88%)
Ran 161 tests (2.73 tests per mutation)
================================================================================

Detailed reports with information about survived mutations and the corresponding parts of code is written to build/reports/pitest/ directory relative to your project root.

Sample PIT report

Sample PIT report

Btw, there is a version 0.29 of PIT just around the corner which provides such interesting features as incremental analysis (i.e. run only mutation tests for code that have been changed). I plan to write a post about it when released, so stay tuned.

Disclaimer. I am the author of gradle-pitest-plugin.

Recently I was playing a little with Hades. Generic DAO implementation which can reduce writing a lot of boiler plate code. So far so good, but I wanted to test some mappings with bidirectional relationship using automated tests. The feature of Hibernate (and JPA implementations in general) is an ability to cache some operations in Session/EntityManager (the first level cache) reducing number of statement sending to database. Generally it’s useful, but when you try to test some DAO operations with rollback at the end of a test (instead of commit) it complicates a few things. Sample situation, persist some object. Hibernate memorize that object should be created in database, but waits with sending insert statement on flush, commit (which causes flush) or related query which needs to have that data in database to perform (like findAll). Using rollback causes that there could be no flush (all read/write operations are performed within EntityManager) and some problems which occur in normal usage from end application could remain undiscovered.
The first idea how to solve that is to call flush on EntityManager, but DAO interface in Hades (and hopefully any other custom made generic DAO) doesn’t offer that command. It could be quite dangerous to give a developer an ability to call flush whenever he/she likes in the application (at least it could have the negative performance impact). Ok, the second idea is to cast interface to it’s implementation. Even in Hades implementation has protected getEntityManager method to allow to use EntityManager directly in specified DAOs. Let’s play. Small utility class in the same package, cast DAO interface to GenericDaoSupport and…

java.lang.ClassCastException: $Proxy38 cannot be cast to org.synyx.hades.dao.orm.GenericJpaDao

Ups, something is wrong. The problem is that our DAO interface implementation autowired with our test is not directly GenericJpaDao, but proxy object made by Spring. It’s not even Hades specific issue. Similar situation could happen when home made generic DAO is used with Spring.

Looking at Spring proxy object in debugger shows it’s a quite complicated object and it wouldn’t be easy to “find” target object. What is more I try to not use dirty hacks when not needed, so I started to look for some other way to get target class using Spring mechanisms itself. After some digging I have found Advised interface which Spring proxy implements. With its help it is possible to do:

targetObject = ((Advised)daoInterface).getTargetSource().getTarget();

which can be without further problems cast to GenericJpaDao which offers getEntityManager. Having EntityManager it’s simple to do flush or detach on given entity. I have found it useful to create an util class offering mentioned functionality for the usage in DAO tests across the project.

package package.with.your.dao.implementation;

import required.classes;

/**
 * Utility class allowing to get EntityManager (to perform flush and/or detach) from DAO interface (available even as Spring proxy).
 *
 * Licensed under the terms of Apache Software License version 2.
 *
 * @author Marcin Zajączkowski, https://solidsoft.wordpress.com/
 */
public final class DaoTestUtil {

    private DaoTestUtil() {
    }

    public static EntityManager getEntityManagerFromSpringEnhancedDaoInterface(GenericDao<?, ?> daoInterface) {

        try {
            Object targetObject = null;
            if (daoInterface instanceof Advised) {
                //Spring proxy
                targetObject = ((Advised)daoInterface).getTargetSource().getTarget();
            } else {
                targetObject = daoInterface;
            }

            GenericJpaDao daoImpl = (GenericJpaDao)targetObject;
            return daoImpl.getEntityManager();
        } catch (Exception e) {
            throw new IllegalArgumentException("Unable to get GenericJpaDao from " + daoInterface.getClass().getName(), e);
        }
    }

    public static void doFlushAndDetachEntityUsingEntityManagerFromDao(GenericDao<?, ?> daoInterface, Object entityDoDetach) {
        EntityManager em = getEntityManagerFromSpringEnhancedDaoInterface(daoInterface);
        em.flush;
        em.detach(entityDoDetach);
    }
}