I have a routes defined in CamelRoutes.xml and I would like to test them by using the wrapping technique described at the bottom of http://camel.apache.org/mock.html.
My CamelRoutes.xml
<route autoStartup="true" xmlns="http://camel.apache.org/schema/spring">
<from uri="direct:start"/>
<to uri="direct:end"/>
</route>
So I created CamelRoutesTest.xml containing:
<import resource="CamelRoutes.xml"/>
<bean id="mockAllEndpoints" class="org.apache.camel.impl.InterceptSendToMockEndpointStrategy"/>
but I am not sure how to create a test that both loads the spring xml AND provides access to the mock endpoints.
If I use..
#ContextConfiguration( locations=("/CamelRoutesTest"))
public class CamelTest extends AbstractJUnit38SpringContextTests
}
then I have no idea how to get the mock endpoints
If I use..
public class CamelTest extends CamelTestSupport
}
then I dont know how to load my camel context..
I can't seem to find an example test on the website that uses CamelTestSupport AND loads routes from spring xml.
Tom you already posted this on the Camel mailing list. I suggest that you write this when you post a Q here as well.
The answer is already posted here
http://camel.465427.n5.nabble.com/Problems-testing-Camel-with-Spring-config-tp4267754p4267754.html
Solved using:
public class CamelTest extends CamelSpringTestSupport {
#Override
protected AbstractXmlApplicationContext createApplicationContext() {
return new ClassPathXmlApplicationContext("/CamelRoutesTest.xml");
}
#Test
#DirtiesContext
public void discover() throws Exception {
getMockEndpoint("mock:my.route.out").expectedMessageCount(1);
template.sendBody("direct:my.route.in", FileUtils.slurpClassPathFile("/samples/sample.data.xml"));
assertMockEndpointsSatisfied();
}
}
Thanks for this solution, #Tom !
I also had a hard time getting Camel to work with my Spring-powered JUnit tests, problem is the suggested CamelSpringJUnit4ClassRunner has now moved from camel-spring.jar to a separate module, camel-spring-test.jar, which is not available in the standard camel-distribution as of 2.9.2.
So I cannot use #RunWith but had to resort to the manual method described in the solution...
Related
As I haven't gotten an answer for my other question here, I am looking for another approach. Is there a way to no not execute or include a fragment during unit testing?
I want to display the version and build number in the footer of my templates, thus I have the following line:
<div class="versionInfo">Version <span th:text="${#buildProperties.getVersion()}"></span></div>
This works well when running the application, but during unit test I get the exception:
No bean named 'buildProperties' available
In the other question I am looking for a way to get this bean during unit test, as an alternative I am now looking for a way to exclude this template during unit tests. Something like this:
<div class="versionInfo" th:if="${!isUnitTest}">Version <span th:text="${#buildProperties.getVersion()}"></span></div>
I am using the following annotations on my test class:
#RunWith(SpringRunner.class)
#WebMvcTest(SimpleController.class)
If it's a standard unit-test, use Mockito to mock the bean:
#RunWith(MockitoJUnitRunner.class)
public class SomeTest{
#Mock
private BuildProperties buildProperties;
...
Or, if it's a Spring MVC test:
#RunWith(SpringRunner.class)
#WebMvcTest(value = MyController.class)
public class MyControllerTest{
#MockBean
private BuildProperties buildProperties;
The version will be null, because all of the methods of the mocked bean returns null.
if you want to emulate a real version you can add something like this to your test or to the setUp() method
given(buildProperties.getVersion()).willReturn("whatever");
--------------- edit
Unfortunately all of the above solutions work only if the buildProperties bean was added to the model directly.
But in your case you use the bean directly as a SpEL bean reference. Unfortunately I don't know any way to check if a bean exists in the context via SpEL.
Also, it's not a good practice to add extra code into your code for checking if it's running in test mode.
So I think the best solution if you create a nested test configuration class and define a default BuildProperties bean there.
#TestConfiguration
public static class TestConfig {
#Bean
BuildProperties buildProperties() {
return new BuildProperties(new Properties());
}
}
Or you can use #Import(TestConfig.class) if you need this extra configuration in multiple test classes.
I got a hint from a colleague that works for this question.
Just add an application.properties to src/test/resources with a custom property:
isUnitTest=true
Then I can simply check for this in my thymeleaf template:
<div class="versionInfo" th:if="${#environment.getProperty('isUnitTest') != 'true'}">Version <span th:text="${#buildProperties.getVersion()}"></span></div>
Though if someone finds a way to achieve this automatically with a thymeleaf setting or property I didn't find so far, I will accept it as an answer.
While testing my Spring classes with EasyMock, I came to this below scenario:
My Spring configuration is taking the original DAO object configured by Spring component-scan rather than my mock DAO object.
Please find my mock, AppContext and test class below:
ApplicationContxt-Test.xml
<context:annotation-config />
<context:component-scan base-package="com.test.testclasses"/>
<import resource="mockServices.xml" />
MockServices.xml
<bean class="org.easymock.EasyMock" factory-method="createMock"
id="codeDAO" primary="true" >
<constructor-arg value="com.test.testclasses.dao.MaintainCodeDAO" />
</bean>
JUnit class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:ApplicationContxt-Test.xml")
public class MaintainCodeServiceImplTest {
#Autowired
private MaintainCodeDAO codeDAO;
#Autowired
private MaintainCodeService maintainCodeService;
#Before
public void setUp() {
EasyMock.reset(codeDAO);
}
#After
public void tearDown() {
EasyMock.reset(codeDAO);
}
#Test
public void shouldAutowireDependencies() {
assertNotNull(codeDAO);
assertNotNull(maintainCodeService);
}
#Test
public void getProcedureByCode_success() throws Exception {
MaintainCodeVO maintainCodeVO = new MaintainCodeVO();
EasyMock.expect(codeDAO.searchProcedureCode(isA(String.class))).andReturn(maintainCodeVO);
EasyMock.replay(codeDAO);
MaintainCodeBO maintainCodeResult = maintainCodeService.getProcedureByCode("test");
EasyMock.verify(codeDAO);
codeDAO.searchProcedureCode("test");
assertNotNull(maintainCodeResult);
EasyMock.reset(codeDAO);
}
}
Here I am mocking codeDAO and while testing the service class, instead of the mock codeDAO, the original DAO object is getting autowired and EasyMock.verify() is throwing exception. Don't know whats the issue. Is there any problem with the above configuration?
I found the solution. The trick was so simple .. I killed one day finding the solution..
So here is the solution:
Just move the mockServices.xml (spring xml with only mock configurations) above context:component-scan...
<import resource="mockServices.xml" />
<context:annotation-config />
<context:component-scan base-package="com.wellpoint.icnotes"/>
Worked like a charm.
If I remember correctly, because of createMock is a generic method, the Spring doesn't work properly while inferring the bean type, it infers it as an Object, so it cannot wire. I suggest not to use the Spring in unit tests, use simple classes.
BTW, EasyMock has it's own DI, just use it: http://easymock.org/user-guide.html#mocking-annotations
It is possible to put mocks into context, e.g. as described here: Autowiring of beans generated by EasyMock factory-method? but for me it is not the best approach, looks clumsy.
If you are using Spring Framework 4.2 or higher, this should work. See the following related issues for details.
https://jira.spring.io/browse/SPR-9567
https://jira.spring.io/browse/SPR-9682
Is there any way to override a bean discovered by component scan?
This is a follow-on question to that posted here:
How to initialise/wire beans in Grails Spock unit tests?
I haven't managed to find an example of where a spring bean is written in java within src/java and which is then unit tested within Grails using Spock.
Given:
// MyBean.java
// this needs to be in java as it is playing with spring-data-neo4j
package com.me;
public class MyBean {
#Autowired
def someNeo4jBeanThatCannotBeTestedByItself
String readFromDb() {
// this will execute code to actually read from a DB
return "Hello from DB";
}
}
Note that "someNeo4jBeanThatCannotBeTestedByItself" is a bean that is associated with spring-data-neo4j and I want to see that my code actually writes stuff here, so I want my unit/integration test to load spring beans (I don't want to mock this out).
What does the test case look like, is it an Integration test? I've tried a couple of variations, but can't get the spring beans to be initialised by Grails test-app.
I know this is old post. As this is not answered yet, i'm trying to answer. If you figured out already, you can ignore.
I believe for this you can write Unit Test. But if this class is under, src/groovy or src/java spring autowire doesn't work. You need to add bean,someNeo4jBeanThatCannotBeTestedByItself and MyBean, in `resources.groovy' file as shown below:
beans={
someNeo4jBean (Neo4jBeanClass)
myBean(MyBean){
someNeo4jBeanThatCannotBeTestedByItself = ref(someNeo4jBean)
}
}
You can remove #Autowired annotation in your bean,MyBean
Now for spec to work , you need to add this property to your spec, static loadExternalBeans = true, then it loads beans present in resources.groovy file.
Sample Spec:
#TestMixin(GrailsUnitTestMixin)
class MyBeanSpec extends Specification {
static loadExternalBeans =true//this loads beans present in resources.groovy
def myBean
def setup() {
myBean= applicationContext.getBean("myBean")
//now you can use this `myBean` in test cases..
}
}
I also had similar situation and i got rid of with this approach.
Hope this helps.
I am currently fronting issues mixing a CXF web service with Spring #Configurable annotation.
From one side I have my CXF web service fully working and configured like this :
<import resource="classpath:some-other-context.xml" />
<jaxws:server id="Init"
serviceClass="package.to.my.ServiceInterface"
address="/">
<jaxws:serviceBean>
<bean class="package.to.my.BADematInitImpl">
</bean>
</jaxws:serviceBean>
</jaxws:server>
<context:spring-configured />
And in my some-other-context.xml is my Spring configuration containing the following Bean's :
#Configurable(autowire = Autowire.BY_TYPE)
public class MyConfigurable {
#Autowired(required=true)
private A a;
#Autowired(required=true)
private B b;
#Autowired(required=true)
private C c;
...
}
But when I try to create a new instance of MyConfigurable bean into my service, I get a NullPointerException due to the null valued supposed-autowired A,B and C objects.
Any idea ?
#Configurable is a marker used by the AOP load-time-weaving stuff. I assume you are not using any AOP, because there is nothing mentioned about it in your question. Second thing: you don't have to use required=true in your #Autowired annotation as true is the default value of required. I would suggest you to change your code like this:
Add these to elements in your spring configuration file:
<context:component-scan base-package="your.pckg.toscan"/>
Documentation says:
Scans the classpath for annotated components that will be
auto-registered as Spring beans. By default, the Spring-provided
#Component, #Repository, #Service, and #Controller stereotypes will
be detected.
<context:annotation-config/>
Documentation says:
Activates various annotations to be detected in bean classes: Spring's
#Required and #Autowired, as well as JSR 250's #PostConstruct,
#PreDestroy and #Resource (if available), JAX-WS's #WebServiceRef (if
available), EJB3's #EJB (if available), and JPA's #PersistenceContext
and #PersistenceUnit (if available). Alternatively, you may choose to
activate the individual BeanPostProcessors for those annotations.
So changing your code to:
#Component
public class MyConfigurable {
#Autowired
private A a;
#Autowired
private B b;
#Autowired
private C c;
...
}
Everything should work just fine.
I finally found out the problem.
I needed to add this configuration into my third-part application XML files :
<context:load-time-weaver/>
... and add this argument to my jvm launch command line :
-javaagent:"path\to\my\spring-agent.jar"
And it just works like a charm.
I understand that this is because Spring needs at some point to have an entity managing its AOP part so that the dependencies are well injected. It would be interesting if someone had further explanations.
Does anyone know how to run unit tests for Liferay portlets? I have found a lot of posts about it (e.g. http://agile-reflections.opnworks.com/2010/06/portlet-unit-testing-with-liferay-6.html) but none works nonetheless.
This may be overkill, but if you're looking for an Enterprise approach with continuous integration testing, this blog gives a very good example: Continuous integration on Liferay: running your Selenium 2 tests on the Tomcat 6 bundle
Unit testing Liferay portlets is quite complicated when ServiceBuilder is utilized.
The reason is that it generates quite heavy services that contain references not only to beans within Portlet, but even to the Portal beans generated by ServiceBuilder.
There are tools like InitUtil.init(); that lets you at least instantiate and use ServiceBuilder entities... not EntityServices though. For that you'd have to use SpringUtil.loadContext(); that requires
System.setProperty("external-properties", "testing.properties");
where testing.properties contains :
spring.configs=META-INF/ext-spring.xml,\
META-INF/base-spring.xml,\
META-INF/dynamic-data-source-spring.xml,\
META-INF/infrastructure-spring.xml,\
META-INF/shard-data-source-spring.xml,\
META-INF/hibernate-spring.xml,\
META-INF/portlet-spring.xml
These are spring definitions to be loaded for testing application context. It all would be OK, but beans from portlet-spring.xml are those heavy services containing references to Portal bean definitions like ResourceService, UserLocalService, CounterLocalService and you would have to load even META-INF/portal-spring.xml and trust me, it's not that easy cause then you'd have to load quite a lot of other stuff.
THE ANSWER:
The truth is, that you most likely won't have to unit test portlet SB services, never. They represent entities with persistence and service layer around. Something that is not to be tested. You just have to mock them and stub their methods, right ?
And the best way for junit and integration testing as to mocking is not using *LocalServiceUtil static classes in your application, because it is almost unmockable.
You just need to create a Spring FactoryBean :
public class PortalFactoryBean implements FactoryBean {
private Class type;
public void setType(final Class type) {
this.type = type;
}
#Override
public Object getObject() throws Exception {
return PortalBeanLocatorUtil.locate(type.getName());
}
#Override
public Class getObjectType() {
return type;
}
}
public class PortletFactoryBean implements FactoryBean {
private Class type;
public void setType(final Class type) {
this.type = type;
}
#Override
public Object getObject() throws Exception {
return PortletBeanLocatorUtil.locate(type.getName());
}
#Override
public Class getObjectType() {
return type;
}
}
<bean id="somePortalBean" class="example.spring.PortalFactoryBean" lazy-init="true">
<property name="type" value="com.liferay.some.util.SomeService"/>
</bean>
<bean id="somePortletBean" class="example.spring.PortletFactoryBean" lazy-init="true">
<property name="type" value="com.example.SomeService"/>
</bean>
#Autowired
private SomeService somePortalBean;
Writing unit/integration tests for this portlet would be quite easy, right ? You just create a spring context for testing and you mock these services :
Using Service Builder is worth it, but you must have some Spring knowledge and play with it for some time. Then it spares a lot of time because it is easy to maintain.
You need to have some third party libraries on classpath.
THe key point is having even portal-impl.jar and other portal dependencies on classpath and having InitUtil.initWithSpring(boolean); load up core spring xml configs that you specify in spring-ext.properties in spring.congigs property, only those services you need. You may need no portal services and only the portlet ones, but this is a problem because your portlet services generated by service builder use the portal services.
Using service builder just needs good knowledge of spring and classloading.
But you need to understand the infrastructure before doing that. There are quite a lot of hacks needed... Like
BeanLocator beanLocator = new BeanLocatorImpl(PortalClassLoaderUtil.getClassLoader(), ac);
PortletBeanLocatorUtil.setBeanLocator("portlet", beanLocator);