File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Testing and the fly likes Can you mock a database? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » Testing
Bookmark "Can you mock a database?" Watch "Can you mock a database?" New topic
Author

Can you mock a database?

Alia Huss
Ranch Hand

Joined: Feb 13, 2009
Posts: 63
Hello!
I'm currently working on a webapp which interracts with a db, quite alot actually.
As it is right now, all my tests make calls to the existing db.
I've heard about test databases which contain test data, how do I create one, and how do I use it in my test cases?

Also, my update and remove use the primary key(an auto-incrementing int called id) to identify which row to update/remove. (Kind of obvious eh..)
Anyway, this means that in my test case I need to send in an int with the remove/update methods,
but since the id is AI the int I send in has to change each time I run the test case.
How can I change that? It's rather tedious to always make sure that there is a row with the id I make the call with.
Will "mocking" the database help with this issue?

Appreciate any help,
Alia
Jeanne Boyarsky
author & internet detective
Marshal

Joined: May 26, 2003
Posts: 31062
    
232

Alia,
While you could mock a database, it sounds like you want to use a real database - just a different one. I suggest taking a look at dbUnit. it allows you to always test with the database in the same state. Which eliminates the row being present problem you described.


[Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
Alia Huss
Ranch Hand

Joined: Feb 13, 2009
Posts: 63
dbUnit, right! I'll check it out, thank you!
Alia Huss
Ranch Hand

Joined: Feb 13, 2009
Posts: 63
Right so I've downloaded the DBUnit .jar and it's in put snuggly along with the other .jars (JUnit, mysql-connector etc.)
But I'm having a problem with using it. I found a tutorial, which I more or less copied and then made to fit my own tests,
this is it:



Is there anything visibly wrong with it?

When I run the test I get this error message:

java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.slf4j.impl.JCLLoggerFactory.getLogger(JCLLoggerFactory.java:69)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:209)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:221)
at org.dbunit.DatabaseTestCase.<clinit>(DatabaseTestCase.java:50)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at junit.framework.TestSuite.createTest(TestSuite.java:54)
at junit.framework.TestSuite.addTestMethod(TestSuite.java:280)
at junit.framework.TestSuite.<init>(TestSuite.java:140)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader.getTest(JUnit3TestLoader.java:102)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader.loadTests(JUnit3TestLoader.java:59)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:445)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
... 17 more

I googled it and on another forum they said that you needed two additional .jars named, slf4j-api-1.5.6.jar and slf4j-jcl-1.5.6.jar, which I also downloaded and added to the buildpath.
Sadly, it still doesn't work. Any ideas on why?

Regards,
Alia
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42919
    
  68
You need the Apache Commons Logging library in the classpath; that's where the "org/apache/commons/logging/LogFactory" class is.
Alia Huss
Ranch Hand

Joined: Feb 13, 2009
Posts: 63
Right, forgive me for being so green, asking all these silly questions *smiles*
But how do I get it?
Do I download it from http://commons.apache.org/downloads/download_logging.cgi? And if so, should I choose the binary one or the source?
And, how do I add a library to my classpath? I can't remember every doing it, not by myself anyhow.

Thanks again!
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42919
    
  68
Yes, that's where you get it; you need the binary build. The file is named common-logging-1.1.1.jar or something like that.

You put it together with the other jar files. You mentioned above that you added jar files for MySQL, DBUnit etc. - just do whatever you did with those file with this one as well.
Alia Huss
Ranch Hand

Joined: Feb 13, 2009
Posts: 63
Right thanks!
And there I got another exception to add to the list.
At


org.dbunit.dataset.DataSetException: java.net.MalformedURLException
at org.dbunit.dataset.xml.FlatXmlProducer.produce(FlatXmlProducer.java:370)
at org.dbunit.dataset.CachedDataSet.<init>(CachedDataSet.java:97)
at org.dbunit.dataset.CachedDataSet.<init>(CachedDataSet.java:81)
at org.dbunit.dataset.xml.FlatXmlDataSet.<init>(FlatXmlDataSet.java:303)
at org.dbunit.dataset.xml.FlatXmlDataSet.<init>(FlatXmlDataSet.java:290)
at com.jayway.konfbooking.test.dbUnit.TestDbUnit.getDataSet(TestDbUnit.java:24)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:150)
at junit.framework.TestCase.runBare(TestCase.java:132)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.net.MalformedURLException
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.dbunit.dataset.xml.FlatXmlProducer.produce(FlatXmlProducer.java:357)
... 19 more

This is getting tiresome *smiles*
I wonder why they don't make tutorials that actually work.
Some info on which libraries were needed would have saved both me and you alot of trouble. Ohwell.
Sod's law and human factor at it's very best. *grins*

So, what does that mean? MalformedURLException?

Thanks for bearing with me!
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42919
    
  68
Where (in which directory) do you keep the file "input.xml"?
Alia Huss
Ranch Hand

Joined: Feb 13, 2009
Posts: 63
It's in the same folder/package as the test class.
And a collegue of mine found where the problem was,
he removed the .getClassLoader() from the code-snippet i showed you in my previous reply, and now it works!

Thank you so much for your help!
Finally I can move on and do some real testing.

Regards,
Alia
Vineela Jyothi
Greenhorn

Joined: Jun 02, 2008
Posts: 3
Any time when you see this exception "org.dbunit.dataset.DataSetException: java.net.MalformedURLException" this is an indication that something wrong with the dataset file (input.xml) that we are referring.
There could be many reasons - Name of the file, path of the file, location of the file.

In my case, i had changed the file name from input.xml to source_test.xml and forgot to change the referece to this in the test class. So every thing messed up.
started getting the "org.dbunit.dataset.DataSetException: java.net.MalformedURLException".. after one hour i understood the reason.

Hope this is useful.
Lukas Eder
Ranch Hand

Joined: Jul 22, 2013
Posts: 41
    
    4

While I generally agree with the other answers indicating that running such tests against an actual database might be better in the end, database mocking can still be useful in some situations - specifically because you mention not wanting to change the ID in your test case for every test run.

jOOQ is a database abstraction framework that includes a mock database as described in this blog post:
http://blog.jooq.org/2013/02/20/easy-mocking-of-your-database (see also some interesting comments about this approach in a syndicated repost on DZone).

Essentially, the jOOQ mock database is a simple JDBC driver that implements the most important JDBC types (Connection, Statement, ResultSet) and loads mock data from a file like this:



The above mock database can then be used as such:



Note, while the above example shows how to use a jOOQ MockConnection with the jOOQ API, you're not required to do that. You can use jOOQ's MockConnection with any application built on top of JDBC, adding jOOQ only as a test dependency.

More useful information can be found in the relevant Javadocs


When Java and SQL work together, great software can evolve. That's why I have created jOOQ. Follow me on blog.jooq.org
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Can you mock a database?