This page describes how to create unit tests inside of a module. For details on writing unit tests in trunk, see the main ?Unit Testing page.
Getting Started With Simple Unit Tests
1. Create Your Test
Place a test like this into your /test/org/openmrs/module/yourmodule folder.package org.openmrs.module.yourmodule;
/** * Tests all methods on MyModuleObject * */ public class MyModuleObjectTest { /** * Make sure that MyModuleObject runs fine with a null * parameter to FeatureX * * @throws Exception */ @Test public void shouldExamineFeatureXOfMyModuleObject() throws Exception { MyModuleObject obj = new MyModuleObject(); String output = obj.someComplicatedCall("argument1"); Assert.assertNotNull(output); } }
2. Run the test
(In Eclipse) Right click on your new class and select Run As ? Unit Test
Getting Started With Service Unit Tests
(or anything using the OpenMRS "Context" object) (or anything using hibernate in your module)
1. Set up your module classpath
You will need to reference most openmrs libraries from your module code (file /.classpath). Your classpath will most likely look very similar to this:
<?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="lib" path="metadata"/> <classpathentry kind="src" path="src"/> <classpathentry kind="src" path="web/src"/> <classpathentry kind="src" path="test"/> <classpathentry kind="lib" path="dist"/> <classpathentry kind="lib" path="lib-common/activation.jar"/> <classpathentry kind="lib" path="lib-common/antlr_2.7.6.jar"/> <classpathentry kind="lib" path="lib-common/asm-1.5.3.jar"/> <classpathentry kind="lib" path="lib-common/c3p0-0.9.1.jar"/> <classpathentry kind="lib" path="lib-common/cglib-2.1_3.jar"/> <classpathentry kind="lib" path="lib-common/commons-collections-3.2.jar"/> <classpathentry kind="lib" path="lib-common/commons-io-1.4.jar"/> <classpathentry kind="lib" path="lib-common/commons-lang-2.4.jar"/> <classpathentry kind="lib" path="lib-common/config-1.0.dtd"/> <classpathentry kind="lib" path="lib-common/config-1.3.dtd"/> <classpathentry kind="lib" path="lib-common/dbunit-2.4.4.jar"/> <classpathentry kind="lib" path="lib-common/dom4j-1.6.1.jar"/> <classpathentry kind="lib" path="lib-common/dwr-205.jar"/> <classpathentry kind="lib" path="lib-common/ehcache-1.2.4.jar"/> <classpathentry kind="lib" path="lib-common/hibernate325-mod.jar"/> <classpathentry kind="lib" path="lib-common/hsqldb-1.8.0.10.jar"/> <classpathentry kind="lib" path="lib-common/jcl-over-slf4j-1.5.6.jar"/> <classpathentry kind="lib" path="lib-common/jsp-api.jar"/> <classpathentry kind="lib" path="lib-common/jstl-1.1.jar"/> <classpathentry kind="lib" path="lib-common/jta.jar"/> <classpathentry kind="lib" path="lib-common/junit-4.4.jar"/> <classpathentry kind="lib" path="lib-common/liquibase-1.9.4-mod.jar"/> <classpathentry kind="lib" path="lib-common/log4j-1.2.15.jar"/> <classpathentry kind="lib" path="lib-common/mail.jar"/> <classpathentry kind="lib" path="lib-common/openmrs-api-1.6.2.13082-dev.jar"/> <classpathentry kind="lib" path="lib-common/resolver.jar"/> <classpathentry kind="lib" path="lib-common/servlet-api.jar"/> <classpathentry kind="lib" path="lib-common/simple-xml-1.6.1-mod.jar"/> <classpathentry kind="lib" path="lib-common/slf4j-api-1.5.6.jar"/> <classpathentry kind="lib" path="lib-common/slf4j-log4j12-1.5.6.jar"/> <classpathentry kind="lib" path="lib-common/spring-2.5.6.jar"/> <classpathentry kind="lib" path="lib-common/spring-test.jar"/> <classpathentry kind="lib" path="lib-common/spring-webmvc.jar"/> <classpathentry kind="lib" path="lib-common/taglibs-standard-1.1.jar"/> <classpathentry kind="lib" path="lib-common/tests-openmrs-api-1.6.2.13082-dev.jar"/> <classpathentry kind="lib" path="lib-common/web-openmrs-api-1.6.2.13082-dev.jar"/> <classpathentry kind="lib" path="lib-common/xercesImpl.jar"/> <classpathentry kind="lib" path="lib-common/xml-apis.jar"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="lib" path="lib-common/hapi-0.5.jar"/> <classpathentry kind="output" path="build"/> </classpath>
(This is assuming you have checked out trunk to the project named "openmrs-trunk")
2. Compile the jar files in trunk
The above classpath assumes that these files exist:
- /openmrs-trunk/dist/openmrs-api-1.4.0.01.5211.jar
- /openmrs-trunk/dist/web-openmrs-api-1.4.0.01.5211.jar
- /openmrs-trunk/dist/tests-openmrs-api-1.4.0.01.5211.jar
They can be compiled with these ant build.xml targets on trunk:
- package-api
- package-web-src
- package-api-tests
And they will be located in the trunk build in the /dist folder. The .classpath file in your module refers to these in that location. You may need to right click and "refresh" the trunk folders if you're having problems.
3. Compile Your Module
The .classpath references the /dist folder because it is assuming your compiled .omod file is in there.
Run the ant package-module target to create your module.
4. Create Your Testpackage org.openmrs.module.yourmodule;
/** * Tests the MyModuleService class and all of its methods * **/ public class MyModuleServiceTest extends BaseModuleContextSensitiveTest { /** * Make sure that MyService runs fine with a null * parameter to getMyModuleObject * * @throws Exception */ @Test public void shouldGetMyModuleObjectWithNullParameter() throws Exception { MyModuleService service = Context.getService(MyModuleService.class)); MyModuleObject obj = service.getMyModuleByName(null); Assert.assertNull(output); } }
5. Run Your Test
(In Eclipse) Right click on your new class and select Run As ? Unit Test
(The BaseModuleContextSensitiveTest class will run through the Spring setup, loads in any omods on the classpath, creates the Context and ServiceContext classes required by the OpenMRS API. This startup takes a few seconds, so when you can, create simple tests that don't need Context and don't extend BaseModuleContextSensistiveTest)
Logging in JUnit Module Tests
- You must have log4j referenced explicitly in your .classpath file
- log4j.xml's parent folder must be in your classpath in order to be found by log4j (like in /metadata or /dist)
- The log4j.xml can will look something like:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%p - %C{1}.%M(%L) |%d{ISO8601}| %m%n" /> </layout> </appender> <logger name="org.openmrs.module.remoteformentry"> <level value="DEBUG" /> </logger> <root> <level value="ERROR" /> <appender-ref ref="CONSOLE" /> </root> </log4j:configuration>
- The log4j.xml can will look something like:
Including Other Required Modules in JUnit Tests
- Package the required module into its omod file and drop it into the /lib-common folder
Extras
- If you've added a log4j.xml file to your metadata directory and metadata is referenced in the .classpath file and you still don't see any log messages in the console during the execution of the test, make sure that the metadata directory comes before all JARs that might have a log4j.xml in them already (i.e. openmrs-api.jar)
- If you create custom tables and map them using hibernate, an error in the <table_name>.hbm.xml can be masked and you will just get an error to the effect that your service cannot be found when you call Context.getService(<your_service>.class). If you compile the module and load it into the OpenMRS web interface, it will tell you the real error.
- If you get an exception like org.openmrs.api.APIException: Service not found: class org.openmrs.module. ... then you may need to do one of two things. First, make sure that you have run the and "package module" task. If you've already done that, then you probably need to fix your build file for the module you're including.
- Open build.xml in the module you're compiling
- Find the "package-jar" target
- Remove the line like "<exclude name="*" />"
- Repackage your jar file and try using it again in the other module
- To skip the authentication username/popup when testing, place these variables into your runtime properties file: junit.username=admin
junit.password=test