A blog mainly about Java

Java EE vs Spring Testing

I’ve recently posted a Tweet about my day to day life. This Tweet said “I’ve reached a point where I can test Spring code in a couple of minutes, and Java EE code in a couple of hours :o(“

I was a bit surprised to read some reactions. In fact, some people asked me to explain this Tweet a bit more… so here I am.

Who Am I? What Am I Doing?

First of all, it’s important to recap who I am and where I come from. Basically, I’ve started working for BEA Systems in 1998, that’s when I discovered J2EE 1.2. In 1999 I was working for a big BEA Systems customer (think of a famous English Airway company ;o) setting up their on-line ticketing. Yes, in 1999 I was doing micro-services (EJBs), with clusters of dozens of services talking to each other in a highly optimized binary protocol (no, not gRPC, its ancestry RMI/IIOP), aggregating logs, setting up clusters, failover, sticky sessions, scalability and so forth. All that with J2EE (and yes, it was in 1999).

When I left BEA Systems I worked on and off with Java EE and Spring. I then wrote a few Java EE books, got involved in the JCP, gave a few talks mainly on Java EE, while I kept working at my customers on Java EE and Spring.

With the entire “Java EE 8 drama” (i.e. the specification wasn’t moving anywhere), the MicroProfile, the Java EE Guardians, EE4J,…. I decided to give myself a “Java EE break”. Since last year I’ve started working with Spring Boot and Angular (thanks to JHipster). Two technologies I wasn’t very familiar with, and I have to say, I’m enjoying it !

So let me rephrase this again: I’ve mostly worked with Java EE, but I haven’t touch a Java EE project for one year, instead, I’ve been working with Spring Boot. That’s why, when I got back to Arquillian recently, it was a bit painful.

Testing

Let’s be plain here: when your code is executed in a managed environment (Java EE, Spring…) Unit Test are (mostly) useless! I have lived this for so long in my projects, that, as a joke, I launched the No Mock Movement back in 2012. Today, in the world of containers and micro services, this is even more true. What is the percentage of your unit tests compare to integration tests? And yes, by unit tests I mean “testing in isolation” with no memory database, no memory web server, no memory message broker… just pure unit tests.

Unit tests in a managed environment are useless. Integration tests are useful, therefore, they should be easy to write.

Testing with Java EE

So, what do you do when you find out that Unit Tests in a managed environment are useless? You write integration tests. And in Java EE, you can choose between Arquillian (my post from 2012), Payara APIs, TomEE APIs… only proprietary APIs actually. So when I read this Tweet I was a bit surprised:

“Proprietary specless”. Interesting. In 2013 I wrote a post on a Java EE 8 Wishlist (basically, about what I wanted to see happening in Java EE 8). Despite the fact that not much from this wishlist has happened, this is what I wrote:

Integration tests should be easier to write. Arquillian already does a fantastic job for integration testing, but we could go further. If we manage to have a single container, and therefore a single container API, then it would be easier to write tests that start a container, lookup for components, check available services, invoke code, check that interceptors have been applied, that Servlets have been constructed, that a Singleton has been initialized at startup by the container…

There is no Java EE specification for managing a container through APIs. If you want to bootstrap the container to do some integration testing, you need to go proprietary (Arquillian, TomEE APIs, Payara APIs…)… like Spring.

I wrote Arquillian tests for years (talked about it, wrote about it). For the Tweets I received, it looks like it is easier to use TomEE or Payara. I have never used those so I can’t tell. But again, this shows that testing in Java EE is not standard.

Testing with Spring

In 2002 when Rod Johnson wrote his famous Expert One–on–One J2EE Design and Development book, his chapter 3 was titled “Testing J2EE Applications“. Yes, in 2002, someone was already looking at how to test a J2EE application. And this same person created Spring, with testing in mind. If you look for the word “cluster” in the Java EE 7 specs (2013), you will only find it once. If today, in 2018, you look for the word “test” in all the Java EE 8 specs, you will not find it very often (if you take out “test” for TCK, and “test” for if statements).

I actually committed a couple of integration tests using Spring Boot recently. There is not much to say when you look at the code. I have a Spring Boot application with a main class that looks like this:

I won’t go into too much technical detail, but if you compare with the code I wrote for my Arquillian post in 2012, testing with Spring Boot is way simpler. With Arquillian you need to package your classes into an archive with all the dependencies (introspecting the pom.xml), and then, deploy this archive into a container. As I said to a friend back at Devoxx BE “Arquillian will be great once we get rid of Shrinkwrap“. What this means is, I don’t want to package code to test it anymore (BTW, I love Shrinkwrap ;o) With Spring, behind the scene it’s more or less the same (no packaging, but classpath scanning and bootstrapping the Spring container), but it’s way simpler.

Java EE is Dead

No, it’s not a Java EE Game Over for me (more on this blog in a few weeks ;o) but I have to say that I am enjoying my new development’s life around JHipster Microservice architecture (Spring Cloud + Angular + Netflix OSS). So I’ll stick to it for now, and I’ll keep a close look at the MicroProfile. And I really hope that EE4J / Microprofile will make sure to have a specified API to control the container (à la Wildfly Swarm), so integration testing will be easy and portable.

Conclusion

Integration tests are important in a managed environment. Even if they are difficult to maintain, they should be as easy to write as possible. Integration tests in Java EE are complex, not portable, still rely on packaging (when using Arquillian), and on a running container (even if Arquillian uses managed container). Spring was created with testing in mind, therefore, integration test were already easier to write years ago. Today, with Spring Boot, it is even easier than ever.

Coming back to the topic of this post: I’ve worked with Spring Boot for more than a year now. I can now write a Spring Boot test in a couple of minutes. Recently I had to use Arquillian. Because I hadn’t use it for a year, and due to the packaging and deployment complexity, it took me a couple of hours.

Related

Post navigation

So glad to read this from you!
back in ~2014 i worked on some J2EE projects and used Arquilian for testing. it really looked cool. i was able to “unit test” my web application. in the last 2 years I’m using spring boot + cloud for every new project. it is by far better and faster than anything i did in the past!

hi Antonio,
really good post! And I like your new style :).
Only one point is not clear to me: I don’t understand why you say that Unit Tests are useless.
If I have a complex business rule to test, I prefer to do it in isolation and not to involve all the dependencies.
Are you saying that you never do any unit test at all? Or are you simply saying that in that case it doesn’t matter whether you use Spring or plain Java EE?

Today, we think that having an in-memory database is Unit Testing. It’s not. If by “Unit Testing” we think of testing code in a completely isolated way, then, yes, only “complex business rules” can apply to that use case. I stil do unit testing, but less than integration testing. As soon as you have a complex business rule that is spread between two beans that inject each other (with @Inject), either you mock the dependency, or, you test both beans with injection (and this is not unit testing anymore).

Nice post Antonio, I have been working for 4 years with Java EE7 and when I switch to springboot for a project I can notice very clearly that everything was easier, at the end I understood that although the standards are very good, in the end you have to use the tool that makes your work easier and more fun,

Hi Antonio,
Thanks for your article. I feel the same comparing Arquillian and @SpringBootTest.
However, I believe that there are a lot of situations, where you do not need Arquillian at all, still complying with a Tests Pyramid strategy like this one: https://martinfowler.com/articles/microservice-testing/
For example using a combination of REST-assured Weld + JUnit, to cover JAX-RS + CDI; and JUnit + EntityManagerFactory to test a JPA layer. (I do not have a solution for those using EJBs,,,)
You could thus reserve Arquillian for the top of the tests pyramid, which is easier to setup at this level as as you can deploy the application package built by your build tool (like maven-war-plugin)

I’m mostly using CDI + Deltaspike + Camel running in TomEE, so it’s not pure Java EE, more like Mictoprofile stack. May be because of that the Arquillian testing is a breeze. And I like the packaging because it provided great flexibility when you can easily swap any resourse file.