Is there any way to use MySQL for JUnit testing with Spring?
I ask this because I have a lot of store procedures in MYSQL and I have noticed that H2 is not working with SPs.
Edit:
Right now my configuration for src/main looks like:
#ComponentScan
#EnableAutoConfiguration
#EnableJpaRepositories
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
}
}
spring.datasource.url=jdbc:mysql://localhost/mydb
spring.datasource.username=user
spring.datasource.password=pw
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
Spring works fine with this configuration. It reads the application.properties, sees the spring.datasource.* and knows that I have set a datasource.
Everything is fine here.
Now, in tests I use something like:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {Application.class})
#Transactional
public class TxServiceTest {
}
This is not going to run the tests against MySQL database. It will run the tests with H2 database. I need to use MySQL for testing because I am using many stored procedures.
I have tried many other combinations but none of them works. What am I missing here?
Possible fix:
I somehow found a way to make it work. I let the main project unchanged and inside my test project I added a new class:
#Configuration
public class PersistenceContext {
#Bean
public DataSource dataSource() {
org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost/mydb?noAccessToProcedureBodies=true");
dataSource.setUsername("xx");
dataSource.setPassword("yy");
return dataSource;
}
}
I don't like this solution too much but it is working.
Sounds like Integration Test. First, make sure that your database is always up-to-date in order to avoid restores and work in common errors. You can use liquibase or flyway to manage deltas. Also, make sure that after execution of the tests the state of the database has not been altered. I mean if you have a table without data at the beginning, after the execution of your test this table must not have data. You can use dbunit or spring-dbunit which is an extension of dbunit for spring to manage this.
In order to use a local mysql database you can use this plugin http://mysql.jcabi.com/
EDIT 01
Replace your h2 dataSource bean:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/demo" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
Related
What is the best way to use spring-test with JUnit to read property files specific to a test method?
The following bean illustrates the intent to search method-level, then class-level, then package-level, then root-level property files:
<bean name="properties" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer" >
<property name="locations">
<list>
<value>classpath:properties.xml</value>
<value>classpath:*/properties.xml</value>
<value>classpath:*/*/properties.xml</value>
<value>classpath:*/*/*.properties.xml</value>
</list>
</property>
</bean>
I've considered using/subclassing PropertySourcesPlaceholderConfigurer or SpringMethodRule, but so far, neither a viable nor elegant solution has occurred to me. spring-test offers a variety of promising class-level annotations, but the stumbling block is that I want to be able to find a method-specific file, e.g.:
classpath:myPackage/myClass/myMethod.properties.xml
If you are just looking for an algorithm that helps you to look up classpath resources based on the current method, you can take inspiration from the ServletTestExecutionListener in the Spring TestContext Framework, specifically the detectDefaultScript() method.
Regards,
Sam (author of the Spring TestContext Framework)
I'm trying to upgrade a current project from Jackson 1.9 to 2.5. Everything was going well until I tried to startup my WAS 7 server and receive this error:
org.springframework.beans.factory.CannotLoadBeanClassException: Error
loading class
[com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider] for bean
with name 'jaxbProvider' defined in ServletContext resource
[/WEB-INF/spring/applicationContext-configuration.xml]: problem with
class file or dependent class; nested exception is
java.lang.NoClassDefFoundError:
com.fasterxml.jackson.jaxrs.base.ProviderBase
This appears to be in relation to trying to register the Jackson Provider in my web.xml below:
<!-- Jackson Provider -->
<bean id="jaxbProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider" >
<property name="mapper" ref="jacksonObjectMapper"/>
</bean>
<bean id="jacksonObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" >
<property name="annotationIntrospector" ref="jacksonAnnotationIntrospector"></property>
</bean>
<bean id="jacksonAnnotationIntrospector" class="com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair" >
<constructor-arg ref="primaryAnnotationIntrospector" />
<constructor-arg ref="secondaryAnnotationIntrospector" />
</bean>
<bean id="primaryAnnotationIntrospector" class="com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector" />
<bean id="secondaryAnnotationIntrospector" class="com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector" />
I have the following jars on my classpath:
jackson-annotations-2.5.0.jar
jackson-core-2.5.0.jar
jackson-databind-2.5.0.jar
jackson-jaxrs-json-provider-2.5.0.jar
jackson-module-jaxb-annotations.2.5.0.jar
Now from my understanding its looking for this fellow:
com.fasterxml.jackson.jaxrs.base.ProviderBase
but can't find it. A google search reveals that class as belonging to a
jackson-jaxrs-provider project, but I can't find a specific jar for that. I think that's because that is just a base for the jackson-jaxrs-json-provider.2.5.0.jar that I already included. So shouldn't it inherently be able to see that base class through the jackson-jaxrs-json-provider.2.5.0.jar??
If anyone has an idea of what could be wrong I would be very appreciative!
Thanks.
If you used Maven, adding jackson-jaxrs-json-provider as a dependency, you will see all the following pulled in
(I had an image from another post with v2.2.3- disregard the version)
As you can see, it does depend on a jackson-jaxrs-base, which is where the ProviderBase is located.
You can download it here (just click the 2.5.0, then the Download Bundle)
I have this working now now, but am lost as to why this problem occurred..
I followed the following
http://pfelitti87.blogspot.co.uk/2012/07/rest-services-with-spring-3-xml-json.html
but i changed the controller method and added #ResponseBody...
#ResponseBody
#ResponseStatus(HttpStatus.OK)
#RequestMapping(value="/names", method=RequestMethod.GET)
public List<Book> getNames() {
return returnData();
}
By adding this i noticed that the output would appear as json, regardless of the extension i specified?...
Any ideas why #RepsonseBody would cause this issue?
The post only works for resolving different views based on different types. It does not work on your case.
If you are using Spring 3.2.x, the configuration below would solve your problem.
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="true"/>
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
<property name="defaultContentType" value="application/json"/>
</bean>
However, if you are using 3.1.x, there are approaches like http://tedyoung.me/2011/07/28/spring-mvc-responsebody and http://springinpractice.com/2012/02/22/supporting-xml-and-json-web-service-endpoints-in-spring-3-1-using-responsebody that might help you.
Spring Test helpfully rolls back any changes made to the database within a test method. This means that it is not necessary to take the time to delete/reload the test data before each test method.
But if you use the #BeforeClass Junit annotation, then that forces the data loader to be static. A question that is explored here: Why must jUnit's fixtureSetup be static?
If the data initialization method is static, so must the data connection methods and the data source..and on and on...forcing everything to be static...which won't work. At which point, I ask - what good is Spring Test's ability to rollback changes when you have to delete/reload the test data anyway for every test??!?!
One approach that works is to create a "data initialiser" class, add it to a test Spring application context that also has your data source, and wire this application context into your tests. This relies on the fact that Spring caches the application context between test invocations.
For example, a test superclass:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:test-application-context.xml"})
#Transactional
public abstract class DataLoadingTest {
#Autowired
protected DatabaseInitialiser databaseInitialiser;
}
With test-application-context.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" .../>
<bean class="DatabaseInitialiser">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
And
public class DatabaseInitialiser extends JdbcDaoSupport {
#PostConstruct
public void load() {
// Initialise your database here: create schema, use DBUnit to load data, etc.
}
}
In this example:
all tests that rely on the database extend DataLoadingTest;
Spring initialises the application context upon first test invocation;
this calls DatabaseInitialiser.load(), via the #PostConstruct annotation;
Spring keeps the application context in a cache;
further test invocations wire in the DatabaseInitialiser from the application context, which is already cached;
tests are transactional, and roll back at the end to the initial data set.
Likewise, DatabaseInitialiser can have a method annotated #PostDestroy to perform any rollback necessary at the end of the whole test run.
We use DBUnit in conjunction with Spring Test extensively. But we do not use the DBUnit functionality to delete data at the end of the test.
We put a bunch of DBUnit inserts for our test data in the #Before method to initialise the test. Then when the test is complete we let the spring rollback functionality bring the database back to its original state.
The biggest problem we have with this is that the DBUnit data has to be loaded before each test, which can be a major performance hit. Most of our tests using DBUnit are read only, testing the behaviour of the application based on certain predefined behaviour. So we have a habit of creating master tests that then run all the fine grain tests in a batch within the same transaction.
Spring Test and DbUnit is two excellent frameworks. But it doesn't make sense to combine them. Since Spring Test execute a rollback on the connection, it cleans up afterwards, while DbUnit cleans up and insert test data in the #Before method.
Use Spring if you're not dependent on any dynamic data and dbUnit otherwise.
Methods annotated with #BeforeTransaction run, like its name suggests, before the transaction of each test is started. If in such method you can detect if the test data is loaded, then one can load the data when needed.
Beware though that the data is left in your (in-memory) database for all subsequent tests.
We use this to load "static" data that would, in a production environment, also be bootstrapped into our database when starting it. This way we actually use exactly the same code and data for our tests, rather than relying on (DbUnit) exports that might become outdated.
You can create a data initializer "bean", since the config is only run once. It follows the same principle as the main answer, but with less code and classes
#Configuration
class DBUnitTest_Config {
protected String PATH = "";
#Bean
public DataSetConfig setupData(DataSource dataSource) throws SQLException {
DataSetExecutorImpl executor = DataSetExecutorImpl.instance(new ConnectionHolderImpl(dataSource.getConnection()));
DataSetConfig dataSetConfig = new DataSetConfig(PATH);
executor.createDataSet(dataSetConfig);
return dataSetConfig;
}
}
Is there a way to (easily) generate a HTML report that contains the tests results ? I am currently using JUnit in addition to Selenium for testing web apps UI.
PS: Given the project structure I am not supposed to use Ant :(
I found the above answers quite useful but not really general purpose, they all need some other major build system like Ant or Maven.
I wanted to generate a report in a simple one-shot command that I could call from anything (from a build, test or just myself) so I have created junit2html which can be found here: https://github.com/inorton/junit2html
You can install it by doing:
pip install junit2html
Alternatively for those using Maven build tool, there is a plugin called Surefire Report.
The report looks like this : Sample
If you could use Ant then you would just use the JUnitReport task as detailed here: http://ant.apache.org/manual/Tasks/junitreport.html, but you mentioned in your question that you're not supposed to use Ant.
I believe that task merely transforms the XML report into HTML so it would be feasible to use any XSLT processor to generate a similar report.
Alternatively, you could switch to using TestNG ( http://testng.org/doc/index.html ) which is very similar to JUnit but has a default HTML report as well as several other cool features.
You can easily do this via ant. Here is a build.xml file for doing this
<project name="genTestReport" default="gen" basedir=".">
<description>
Generate the HTML report from JUnit XML files
</description>
<target name="gen">
<property name="genReportDir" location="${basedir}/unitTestReports"/>
<delete dir="${genReportDir}"/>
<mkdir dir="${genReportDir}"/>
<junitreport todir="${basedir}/unitTestReports">
<fileset dir="${basedir}">
<include name="**/TEST-*.xml"/>
</fileset>
<report format="frames" todir="${genReportDir}/html"/>
</junitreport>
</target>
</project>
This will find files with the format TEST-*.xml and generate reports into a folder named unitTestReports.
To run this (assuming the above file is called buildTestReports.xml) run the following command in the terminal:
ant -buildfile buildTestReports.xml
Junit xml format is used outside of Java/Maven/Ant word.
Jenkins with http://wiki.jenkins-ci.org/display/JENKINS/xUnit+Plugin is a solution.
For the one shot solution I have found this tool that does the job:
https://www.npmjs.com/package/junit-viewer
junit-viewer --results=surefire-reports --save=file_location.html
--results= is directory with xml files (test reports)
I found xunit-viewer, which has deprecated junit-viewer mentioned by #daniel-kristof-kiss.
It is very simple, automatically recursively collects all relevant files in ANT Junit XML format and creates a single html-file with filtering and other sweet features.
I use it to upload test results from Travis builds as Travis has no other support for collecting standard formatted test results output.
There are multiple options available for generating HTML reports for Selenium WebDriver scripts.
1. Use the JUNIT TestWatcher class for creating your own Selenium HTML reports
The TestWatcher JUNIT class allows overriding the failed() and succeeded() JUNIT methods that are called automatically when JUNIT tests fail or pass.
The TestWatcher JUNIT class allows overriding the following methods:
protected void failed(Throwable e, Description description)
failed() method is invoked when a test fails
protected void finished(Description description)
finished() method is invoked when a test method finishes (whether passing or failing)
protected void skipped(AssumptionViolatedException e, Description
description)
skipped() method is invoked when a test is skipped due to a failed assumption.
protected void starting(Description description)
starting() method is invoked when a test is about to start
protected void succeeded(Description description)
succeeded() method is invoked when a test succeeds
See below sample code for this case:
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class TestClass2 extends WatchManClassConsole {
#Test public void testScript1() {
assertTrue(1 < 2); >
}
#Test public void testScript2() {
assertTrue(1 > 2);
}
#Test public void testScript3() {
assertTrue(1 < 2);
}
#Test public void testScript4() {
assertTrue(1 > 2);
}
}
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class WatchManClassConsole {
#Rule public TestRule watchman = new TestWatcher() {
#Override public Statement apply(Statement base, Description description) {
return super.apply(base, description);
}
#Override protected void succeeded(Description description) {
System.out.println(description.getDisplayName() + " " + "success!");
}
#Override protected void failed(Throwable e, Description description) {
System.out.println(description.getDisplayName() + " " + e.getClass().getSimpleName());
}
};
}
2. Use the Allure Reporting framework
Allure framework can help with generating HTML reports for your Selenium WebDriver projects.
The reporting framework is very flexible and it works with many programming languages and unit testing frameworks.
You can read everything about it at http://allure.qatools.ru/.
You will need the following dependencies and plugins to be added to your pom.xml file
maven surefire
aspectjweaver
allure adapter
See more details including code samples on this article:
http://test-able.blogspot.com/2015/10/create-selenium-html-reports-with-allure-framework.html
I have created a JUnit parser/viewer that runs directly in the browser. It supports conversion to JSON and the HTML report can be easily reused.
https://lotterfriends.github.io/online-junit-parser/
If you are still missing a feature feel free to create an issue on Github. :)