Unit Testing
Contents |
We are currently using JUnit for unit testing. See Unit Test Conventions.
Getting Started
To test a class that is not associated with the Context unit testing is a two step process:
- Create your test class in /test/api/org/openmrs:
- Run your test class. In eclipse:
- Right click on the class name in the "Navigator" or "Package Explorer" view
- Select "Run As" → JUnit Test
- No number 3! I said only a "2 step process"! Go! Test your world!
A good example of a basic junit test would be the RoleTest
Testing the OpenMRS API (and Other Context Sensitive Classes)
To test a class that requires the Context object and method calls, simply extend BaseContextSensitiveTest. The BaseContextSensitiveTest class will run through the Spring setup to create the Context and ServiceContext classes required by the OpenMRS API. This startup takes a few seconds, so when you can, create simple tests that only extend TestCase and do not call Context.*.
- Create your test class in /test/api/org/openmrs/api:
... public class MyServiceTest extends BaseContextSensitiveTest { ...
- Run your test class. In eclipse:
- Right click on the class name in the "Navigator" or "Package Explorer" view
- Select "Run As" → JUnit Test
A good example of a Context sensitive junit test would be the UserServiceTest
By default, the Context is set up to run against an in-memory database called hsql. This database is automatically built from the hibernate mapping files that Spring knows about. To use your mysql database defined by your runtime properties, override the BaseContextSensitiveTest.useInMemoryDatabase() code> method and have it return false.
If you are running against the in-memory database, you need to do something like this:
... initializeInMemoryDatabase(); authenticate(); executeDataSet("org/openmrs/synchronization/engine/include/SyncCreateTest.xml"); ...
An example of an xml dataset definition is initialInMemoryTestDataSet.xml. (This code is automatically run by the initializeInMemoryDatabase() call.)
If you don't want to hand-write the XML, you may follow the strategy detailed in CreateInitialDataSet.java.
Batch JUnit Testing
- Run the ant target
junit-report code> found in the OpenMRS build.xml file - The generated reports can be viewed with /build/junit-report/index.html
JUnit Environment Variables
JUnit Environment variables can override system environment variables. For example, if you want a different OPENMRS_RUNTIME_PROPERTIES_FILE for JUnit.
- Right Click on a JUnit test. For example, CreateInitialDataSet.java.
- Select Run As --> Open Run Dialog
- Select the Environment tab and add a New environment variable.
Resources
- See Module Unit Testing for using JUnit in modules.
- See Load Testing
- See GUI Unit Testing
FAQ
- How do I create a method in my junit test class that will not be run as a test method?
- The only methods run by JUnit are named test____. Just don't start your method name with 'test'.
- How can I authenticate to the Context without putting my username and password in the code?
- Use the authenticate() method found in BaseContextSensitiveTest
- That authenticate method is awesome...but I want to authenticate without user intervention. How can I do that easily?
- Define two properties in your runtime properties file: junit.username and junit.password.
- How can I have my Context sensitive tests actually commit to the database instead of rolling back at the end of the tests?
- Call the
setComplete() code> method in your test method (Note: This only makes sense if you've chosen to not use the in-memory hsql database)
- Why am I getting the error
org.openmrs.api.APIException: Service not found: interface org.openmrs.api ..... code> in my unit test? - You're trying to use a basic unit test to do Context/API testing. Extend
BaseContextSensitiveTest code> instead of justTestCase code>
- Why am I getting the error
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here code> in my test? - You're probably calling either BaseContextSensitiveTest.getConnection() or initializeInMemoryDatabase() outside of the transaction. It is best to call this from either
onSetUp''<u>In</u>''Transaction code> or from your test methods
- Is there a tool for creating the xmls used in the unit tests or are they made by hand?
- You can write it by hand if you want, but the easiest way is to generate the xml off of your current openmrs database. Use the org.openmrs.test.CreateInitialDataSet file to generate it.
