[hibernate-dev] Making tests nicer with lambdas

Gunnar Morling gunnar at hibernate.org
Fri Jun 13 04:26:36 EDT 2014


For those interested, Java 8 actually intends to allow for "optional
returns" from Lambda expressions, i.e. there may be two overloaded versions
of a method, one expecting a Lambda expression with a return and one
without.

So the previous example could actually be written like this:

    Foo foo = inTransaction( (session, tx) -> {
        Foo f = new Foo();
        em.persist( f );
        return f;
  } );

    inTransaction( (session, tx) -> {
        Foo f = em.find( Foo.class, foo.getId() );
        ...
  } );


So the first invocation would make use of TransactionBoundaryWithResult and
the second would use TransactionBoundary with the following definitions:

    public void inTransaction(TransactionBoundary transactionBoundary) {
...}
    public <T> T inTransaction(TransactionBoundaryWithResult<T>
transactionBoundary) {

and

    @FunctionalInterface
    public interface TransactionBoundary {
        void execute(Session session, Transaction transaction);
    }

    @FunctionalInterface
    public interface TransactionBoundaryWithResult<T> {
        T execute(Session session, Transaction transaction);
    }

Unfortunately though, JDK 8u5 and the Eclipse compiler can't distinguish
the two inTransaction() methods and falsely report an ambiguity error at
the call-site. It works as of 8u20.

--Gunnar




2014-05-16 10:25 GMT+02:00 Gunnar Morling <gunnar at hibernate.org>:

> I had envisioned inTransactionWithResult() for that purpose. This returns
> a value which can be used in the next lambda expression:
>
>     Foo foo = inTransactionWithResult( (session, tx) -> {
>         Foo f = new Foo();
>         em.persist( f );
>   } );
>
>     inTransaction( (session, tx) -> {
>         Foo f = em.find( Foo.class, foo.getId() );
>         ...
>   } );
>
> But admittedly it doesn't work that nicely when more then one value needs
> to be passed between lambdas. Also there is naming conflict between the
> variable within the lambda expression and the variable holding the result.
> One would naturally like to use the same name - as it is the same thing -
> but that's not possible.
>
> I didn't pursue the idea any further since then.
>
> --Gunnar
>
>
>
>
>
>
>
>
>
> 2014-05-16 9:51 GMT+02:00 Emmanuel Bernard <emmanuel at hibernate.org>:
>
> These kind of tests are actually not in isolations between lambdas. You
>> often want to pass an id or value between blocks to be reused. I don't
>> think lambdas are porous enough for that. That would be surprising.
>>
>> Emmanuel
>>
>> On Fri 2014-04-25 10:41, Gunnar Morling wrote:
>> > Hey,
>> >
>> > I've played around a bit with the idea of using Java 8 lambdas to make
>> > tests easier to write and read. We have many tests which open a session
>> and
>> > TX, do some stuff, commit, open a new TX (and/or session), do some
>> > assertions and so on:
>> >
>> >     Session session = openSession();
>> >   Transaction transaction = session.beginTransaction();
>> >
>> >     // heavy testing action...
>> >     transaction.commit();
>> >   session.clear();
>> >
>> >     transaction = session.beginTransaction();
>> >
>> >     // load, assert...
>> >   transaction.commit();
>> >   session.clear();
>> >
>> > The same could look like this using Java 8 lambdas:
>> >
>> >     Foo foo = inTransactionWithResult( (session, tx) -> {
>> >         // heavy testing action...
>> >   } );
>> >
>> >     inTransaction( (session, tx) -> {
>> >         // load, assert...
>> >   } );
>> >
>> > Extracting the session/TX handling removes quite some clutter and
>> focuses
>> > more on the actual testing logic. It also avoids problems due to
>> dangling
>> > transactions e.g. in case of assertion failures as the TX handling is
>> done
>> > in a finally block in inTransaction().
>> >
>> > At this point I've just done a quick POC and would be interested in
>> > feedback whether you think that's worth pursuing or not. Note that
>> > different language levels can be used for test and main code, so we
>> could
>> > make use of lambdas in tests while ensuring Java 6 compatibility for the
>> > delivered artifacts.
>> >
>> > --Gunnar
>> > _______________________________________________
>> > hibernate-dev mailing list
>> > hibernate-dev at lists.jboss.org
>> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>
>
>


More information about the hibernate-dev mailing list