javaee / javaee-spec

Java EE Platform Specification
https://javaee.github.io/javaee-spec
Other
389 stars 69 forks source link

Provide a CDI-Embedded Container to faciliate testing #35

Open glassfishrobot opened 10 years ago

glassfishrobot commented 10 years ago

It would be quite easy to test JEE Applications using a CDI container that runs outside the Application Server. Weld already provides a CDI Container for Java SE (Weld-SE). I have been using this approach to test JEE Applications in several customer projects and the feedback has been good.

Please see this post for detailed information about this approach: http://blog.novatec-gmbh.de/unit-testing-jee-applications-cdi/

The source code can be found on: https://github.com/NovaTecConsulting/BeanTest

The example described in the post uses standard CDI features to make it possible to test JEE applications with (almost) all its dependencies resolved by the CDI Container. It runs like a normal Unit test, which means that the tests need milliseconds to run. It uses local transactions which it is ok for testing purposes. It also uses CDI extensions to "convert" EJBs into normal CDI Beans, so it aligns very well in the direction where JEE8 is going, namely, CDI instead of EJBs.

I think this feature will help a lot with testing. Besides, the approach uses other well established specs like JPA. I think that the technical aspects for this feature are already solved. The specs and infrastructure needed are already out there.

I know there is an Embedded Container already but it is very hard (almost impossible) to properly configure it in large projects.

Arquillian is a very good framework but I think it is used more for integration tests (deployment is still required in most cases).

glassfishrobot commented 10 years ago

Reported by cbarragan

glassfishrobot commented 10 years ago

reza_rahman said: I believe one of the primary goals of CDI.next() is to standardize a Java SE runtime (like Weld SE). Is this all you are asking for or is there more to it?

glassfishrobot commented 10 years ago

cbarragan said: I think the CDI SE runtime is a big part of it. It also depends, whether or not EJBs will be CDI Beans with stereotypes in JEE8. Using CDI SE for unit testing is not new. The "trick" in the example is the extension that changes the beans' meta data, so that the CDI container is able to inject EJBs.

I also had to write an interceptor to propagate the local transactions and I usually have to create another persistence unit for testing. I used Mockito to mock external dependencies as well.

I think, it would be nice if those steps: the extension, the interceptor for transactions, Mockito and the persistence unit were not necessary to unit test a jee application. So, yes I am asking for more. Perhaps I should have named the request "Unit Test facility that relies on CDI". CDI is a big part of this feature but other aspects are also important. It would be nice to be able to use this feature almost out-of-the-box following the convention over configuration paradigm. For instance, the JPA-Provider knows somehow (profile?) it is not running in the app server and therefore, it accepts local transactions even though a jta data source was configured (this is just an idea of course).

I guess, the original purpose of the embedded App-Server container was to facilitate testing. Maybe this feature could finally achieve that. As I mentioned, a lot of the infrastructure is already there, so I think it would not be that difficult to provide this feature.

glassfishrobot commented 10 years ago

reza_rahman said: Do you mind taking a look at this JIRA and see what you think: https://java.net/jira/browse/JAVAEE_SPEC-27. Keep in mind, even if we did decouple the EJB services from the component model, it would still likely not be part of CDI (although they might be CDI system interceptors). For example, in Java EE 7, @Transactional was standardized in JTA, not CDI.

glassfishrobot commented 10 years ago

@bshannon said: Please note, there is no "JEE". The correct name is "Java EE". Thanks. https://java.net/projects/javaee-spec/pages/JEE

glassfishrobot commented 10 years ago

cbarragan said: @reza: I took a look at #27. I think the point 4 "Standardize a container that includes everything but the web/presentation/interface tier APIs " is more or less what I am requesting. The big difference though is that deployment is still required somehow, so I think it is more focused on integration tests.

With the approach I'm proposing there is no need for deployment whatsoever. It is more focused on "unit" testing (although strictly speaking it is not a unit test anymore) I think that's the killer feature. There are well defined boundaries regarding what it is going to be tested with this approach. The boundary is usually a "module". The typical big Java EE project consists of several of these modules. It usually takes a lot of time to do integration tests of all the modules, so the feedback is quite slow. This approach, using CDI as a container, actually allows the developer to do TDD. You can test a bean, change it a little bit and test it again in a couple of seconds. I think, that would be very well welcome by the Java EE developers

@Bill: Sorry about that.

glassfishrobot commented 10 years ago

reza_rahman said: To summarize, are you basically asking for a Shrinkwrap like API for standardized embedded containers (most of the time, this is what Jetty does) or simply applying container services to the contents of the class-path (this is basically what Spring/Guice testing does in 90% of cases)? Note the several options in my JIRA issue as options for "deployment".

Do keep in mind, Mockito, JMock, etc are not standards. While you can easily create a plugin that uses these tools (say on top of Arquillian) and interfaces with a standard embedded container via it's "deployment" API, it's not easy to reference non-standard tools in Java EE.

glassfishrobot commented 10 years ago

cbarragan said: I am asking the later, namely, applying container services to the contents of the class-path. This is what I am currently doing with this approach. I use a CDI container to be able to simulate some of the services provided by the Java EE application server like transactions and dependency injection. I think that is important to highlight: It is not about providing all the services but a simulated environment to at least be able to test basic things. This is not a replacement of integration tests. This is a way to do unit-test-like testing with minimal configuration and mocks.

It would be very nice, if a developer were able to do something like the following in a Java SE environment (i.e. unit tests) without having to deploy anyhting:

MyEjb myEbj = Container.getBean(MyEjb.class);

I know Mockito and similar tools are not standard. Maybe there can be another way to provide this mocks like what deltaspike does with partial beans: http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/deltaspike-partialbean-advanced/

glassfishrobot commented 7 years ago

This issue was imported from java.net JIRA JAVAEE_SPEC-35