How to setup JUnit tests for Glassfish Embeddable EJBContainer + EclipseLink JPA? - junit

I'm trying to use EJB 3.1 Embeddable EJBContainer on Glassfish 3.1 for integration
testing my EJB's. There's a classloading issue I can't figure out.
My ejbs are build into dum-ejb.jar. They use EclipseLink JPA. I also create EJB client jar dum-ejb-client.jar, while attempting to fight the classloading issues. Client jar contains the EJB interfaces, and Entity classes (which are usually parameters or returns values). Client jar also contains a lot of unneeded classes that could be dropped (but I don't see how it would solve the problem).
The problem is that since EclipseLink does bytecode weaving to the Entity classes, the Entity classes must not be in the classpath when the junit tests are run: http://www.java.net/forum/topic/glassfish/glassfish/embedded-glassfish-and-weaving
I can do that and configure classpath so that dum-ejb.jar is not included. If I use EJBContainer so that I look up my service as a java.lang.Object and call it's methods via reflection, the test works. But of course, that's not how I want to write my tests.
Typical test would be like:
#Test
public void testInEJBContainer() throws Exception {
File ejbJarFile = new File("target/dum/dum-ejb.jar");
Map props = new HashMap();
props.put("org.glassfish.ejb.embedded.glassfish.instance.root",
"target/classes/instance-root");
props.put(EJBContainer.MODULES, new File[]{ejbJarFile});
EJBContainer container = EJBContainer.createEJBContainer(props);
CompanyService = (CompanyService)
container.getContext().lookup("java:global/dum/CompanyServiceImpl");
log.info("result of findAll() " + service.findAll(false));
}
How could I run the test if CompanyService interface, and returned Company Entity classes can not be in the classpath?
Even if dum-ejb.jar is not on classpath, and dum-ejb-client.jar is, EclipseLink weaving gets broken.
Isn't this exactly the typical use case for EJBContainer, shouldn't there be a simple solution to this?

Turns out I ran into classloading problems since I was running the EJBContainer from maven ear project.
When I run it from the maven ejb project itself, there's no such issues and EJBContainer is easy to use.

Related

ConnectionFactory exception Camel testing JMS

I'm doing my first steps with Camel and currently working on writing a simple junit test using jms as a transport.
Here is a code I wrote:
public class FirstMockTest extends CamelTestSupport {
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("jms:topic:quote")
.to("mock:quote");
}
};
}
#Test
public void testMessageCount() throws InterruptedException {
MockEndpoint mockEndpoint = getMockEndpoint("mock:quote");
mockEndpoint.setExpectedMessageCount(1);
template.sendBody("jms:topic:quote", "Camel rocks");
mockEndpoint.assertIsSatisfied();
}
}
Because of missing connectionFactory I got the following exception:
org.apache.camel.FailedToCreateRouteException: Failed to create route route1: Route(route1)[[From[jms:topic:quote]] -> [To[mock:quote]]] because of connectionFactory must be specified
I'm able to fix it adding the following lines to my route:
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory("vm://localhost?roker.persistent=false");
context.addComponent("jms", JmsComponent.jmsComponent(connectionFactory));
But I don't like I'm adding some components to my context inside the route. Also, If i want to have another route I will need to do it again.
Obviously, there should be another way to tell my test about connection factory.
Thank you in advance!
It's a good idea to define the JMS connection factory outside of your Camel context and, if possible, reuse it. How to do that depends on your component model / execution environment.
If you're using a Java SE version that supports CDI, that would be an obvious choice. You'd define your JMS connection factory as a named component once and inject it everywhere you need it. Have a look at http://camel.apache.org/cdi.html and for testing support at http://camel.apache.org/cdi-testing.html
If you're using Spring, define your connection factory as a spring bean and inject it wherever you need it.
If you're using Java EE on an application server, you'd usually define the JMS connection factory using the mechanisms of that app server. You'd then look up the JMS connection factory using JNDI.
If you're running in an OSGi container, you should define the JMS connection factory in its own bundle and export it as an OSGi service. In the bundle of your Camel context, import that OSGi servide and inject it into the Camel context.
In all above cases you should consider using a pooled JMS connection factory.
For CDI, Spring and OSGi, have a look at: http://activemq.apache.org/maven/5.14.5/apidocs/org/apache/activemq/jms/pool/PooledConnectionFactory.html
For Java EE the way how to set pooling parameters depends on your app server.
Note of caution: for Java SE CDI and Spring there should be only one Camel context per application (you can have many routes, though). So if the JMS connection factory is only used in that one Camel context, there is not much reuse. Despite that I still think it's preferable to define the JMS connection outside of the Camel context in a separate component. It's, well, cleaner.
Since you are writing a junit you can avoid creating a ConnectionFactory if you stub the jms endpoint. You can name the endpoint as stub:jms:topic:quote. Have a look at sample example at link https://github.com/camelinaction/camelinaction2/blob/master/chapter9/mock/src/test/java/camelinaction/FirstMockTest.java

Spring-test and ServletContextListener in web.xml

i try to use spring-test(3.2.10) and integration tests with TestNG by this link.
I created RootTest.java
#WebAppConfiguration
#ContextConfiguration("file:src/test/resources/root-context2.xml")
public class ReferenceServiceTest extends AbstractTestNGSpringContextTests {
...
spring context loaded success. But my global variables not instantiated because web.xml ignored. In web.xml i have my own "listener-class"(implementation of ServletContextListener) and "context-param". How i can load web.xml context(and calls all application startup listeners) with spring integration test context?
As stated in the reference manual, the Spring MVC Test Framework...
"loads the actual Spring configuration through the TestContext
framework and always uses the DispatcherServlet to process requests
thus approximating full integration tests without requiring a running
Servlet container."
The key point there is "without ... a Servlet container". Thus web.xml does not come into the picture here. In other words, there is no way for configuration in web.xml to have an affect on integration tests using the Spring MVC Test Framework.
Now, having said that, it is possible to register a Servlet Filter with MockMvc like this:
mockMvcBuilder.addFilters(myServletFilter);
or
mockMvcBuilder.addFilters(myResourceFilter, "/resources/*");
And you can configure context-param entries by adding them manually to the ServletContext (which is actually Spring's MockServletContext) before you execute assertions on MockMvc like this:
wac.getServletContext().setInitParameter(name, value);
But... there is no way to configure a ServletContextListener using Spring MVC Test. If you want to have a listener applied to all of your requests that pass through Spring MVC, as an alternative you could consider implementing a custom HandlerInterceptor or WebRequestInterceptor (see Configuring interceptors in the reference manual).
Regards,
Sam
Try with a MockServletContext
#Before
public void before() {
MockServletContext mockServletContext = new MockServletContext();
mockServletContext.setInitParameter("parameterName", "parameterValue");
new MyListenerClass().contextInitialized(new ServletContextEvent(mockServletContext));
}

Class loading collision between Robolectric and Powermock

I'm trying to write a test that needs both Robolectric 2.2 and PowerMock, as the code under test depends on some Android libraries and third party libraries with final classes that I need to mock.
Given that I'm forced to use the Robolectric test runner through:
#RunWith(RobolectricTestRunner.class)
...I cannot use the PowerMock test runner, so I'm trying to go with the PowerMock java agent alternative, without luck so far.
I have setup everything according to this guide but I'm facing a collision problem between classes required by the javaagent library and by robolectric through its dependency with asm-1.4. Both depend on
org.objectweb.asm.ClassVisitor
, but javaagent-1.5.1 ships with its own version where ClassVisitor is an interface while asm-1.4 version for the same namespace is an abstract class, with the corresponding error at runtime:
java.lang.IncompatibleClassChangeError: class org.objectweb.asm.tree.ClassNode has interface org.objectweb.asm.ClassVisitor as super class
I have even tried to modify the javaagent library jar to entirely remove the org.objectew.asm classes in there, but that doesn't work as ClassNotFoundException happens afterwards due to some other classes needed in the org.objectweb.asm package that only ship in the javaagent library jar, and not in the asm one.
Any ideas? According to examples out there the agent seems to work fine with, at least, the Spring test runner.
I had the same problem and while I didn't solve this problem as such, I wanted to share my approach, which removes the need for PowerMock (which is always a good thing in my view): I wanted to mock a call to
Fragment fooFragment = new FooFragment();
So what I did was addanother level of indirection. I created a FragmentProvider class:
public FragmentFactory fragmentFactory = new FragmentFactory();
[...]
Fragment fooFragment = fragmentFactory.getFooFragment();
After i did this, I could just mock out the factory with standard Mockito, like this:
FragmentFactory mockFactory = mock(FragmentFactory.class);
activity.fragmentFactory = mockFactory;
when(mockFactory.getFooFragment()).thenReturn(mockFooFragment);

mock cdi interceptors during junit tests

I have a complex Java EE 6 app with a web module, an EJB module and some utility jars.
I want to do some integration tests with Junit. Therefore I use the openwebbeans cdi container (Thanks to Mr. Struberg http://struberg.wordpress.com/2012/03/17/controlling-cdi-containers-in-se-and-ee/)
It works perfectly. I can start a complete cdi container in a Junit test.
My problem is that I have some interceptors in my application which cannot run in a Junit test (MQ-, persistence- and transaction-interceptors). So I want to mock these interceptor implementations.
Does anybody know how to do this?
To whom it may concern ;-)
At the end I solved my issue with clean Java EE techniques. I provided a method which observes the ProcessAnnotatedType event. This method evaluates the type which is processed and if it is one of my interceptors, then I veto the processing.
public void processAnnotatedType(#Observes final ProcessAnnotatedType<?> event, final BeanManager manager) {
if (event.getAnnotatedType().getJavaClass().equals(PrivilegeCheckingInterceptor.class)) {
event.veto();
}
}
Why not just test in the container of choice with Arquillian? The other option which comes to mind would be to add in interceptors with mock functionality and exclude the actual interceptor implementation when you start the CDI container.
You can also run tests with embedded OpenEJB.
This link http://openejb.apache.org/examples-trunk/interceptors/ may be useful - perhaps setting property of 'openejb.deployments.classpath.exclude' could help.
Another option of "vetoing" could be through Deltaspike #Exclude annotation. It can veto beans based on ProjectStage.
Example:
#Exclude(ifProjectStage = ProjectStage.UnitTest.class)
public class MyInterceptor {
}
Then in your test you can activate the project stage using Deltapike test control module, example:
#RunWith(CdiTestRunner.class)
#TestControl(projectStage = UnitTest.class)
public class TestStageControl {
#Test...
}

Castle Windsor Configuration Over Multiple Projects and unit testing

I have a solution with multiple projects and one of these projects is my service class which calls into the persistence manager.
I would like to write a unit test as follows:
[Test]
public void Create_HappyPath_Success()
{
// Arrange
UnitOfMeasure unitOfMeasure = new UnitOfMeasure();
unitOfMeasure.Code = "Some new unit of measure";
unitOfMeasure.DataOwner = 1;
// Act
this.UoMService.Create(unitOfMeasure); // Fails here as UoMService is null
// Assert something
}
Now, I'm getting a null reference exception on this line:
this.UoMService.Create(unitOfMeasure); // Fails here as UoMService is null
I believe that it's due to the fact that Castle Windsor is not getting called and hence the UoMService isn't getting instantiated. My Castle Windsor application installer is defined in another project i.e. my ASP.NET MVC project. So my first question is whether it's possible to reuse that installer to run my Unit Tests.
Now to get around this problem, I created a new installer in my unit test project by linking to the installer in my web project. Then I used the following code in my set up:
[SetUp]
public void ControllersInstallerTests()
{
this.containerWithControllers = new WindsorContainer();
IoC.Initialize(this.containerWithControllers);
this.containerWithControllers.Install(FromAssembly.This());
}
This time when I run the tests, I get the following error:
SetUp : Castle.Windsor.Configuration.Interpreters.XmlProcessor.ConfigurationProcessingException : Error processing node resource FileResource: [] []
----> Castle.Core.Resource.ResourceException : File C:\Projects\DavidPM\Services\MyProject.Services.ServiceImpl.Test.Unit\bin\Debug\Config\Windsor.config could not be found
The question is why is it looking in the bin\Debug folder?
As a newbie with Castle Windsor, I am not sure what I should be doing to hook into Castle Windsor for my unit tests.
You should not be hooking up your IoC container in your unit tests. During production, your IoC container will resolve dependencies. During unit tests, you create the dependencies as part of your tests -- usually using a mocking framework so you can test in isolation.
make your config file copy to output directory