Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated to reflect more moden standards

...

Code Block
public void getAllUsers_shouldNotReturnNull() throws Exception {
  Assert.assertNotNull(Context.getUserService().getAllUsers());
}


Note, however, that it is preferable to statically import the members and use Hamcrest matchers such as the below:

Code Block
java
java
public void getAllUsers_shouldNotReturnNull() throws Exception {
    // assertThat is imported from Assert; notNullValue is imported from Matchers
    assertThat(Context.getUserService().getAllUsers(), notNullValue());
}


When in a BaseContextSensitiveTest type of Test classtest class that extends BaseContextSensitiveTest, some test data is are available to you automatically. See the standardTestDataset.xml and initialInMemoryTestDataSet.xml files for content.  See "Setting Up the Expected Database" below for how to add your own test data. 

...

Be sure to read our Unit Testing Conventions as well.

Getting Started

...

To test a class that is not associated with the Context unit testing is only a three step process:

1) Add an @should annotation to the object you're testingIdentify the method you want to test:

Code Block
package org.openmrs;

**
* This does blah blah blah...
*/
public class MyObject {

.......

**
* This method does something blah blah blah
* @param arg this does something
* @return the Object
* @should do x given some non
null
*/
public Object someComplicatedCall(String arg) throws Exception {
     ...does something interesting here...
   }
}

2) Use the Eclipse plugin to generate a test method in the matching Test classCreate a test case for it:

Code Block
package org.openmrs;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

**
* Tests against the java pojo for MyObject
*/
public class MyObjectTest {

    **
    * Get the X output of ComplicatedCall when given a non null argument
*/ @Test @Verifies(value = "should*/
do x given some non@Test
null", method = "someComplicatedCall(String)") public void someComplicatedCall_shouldDoXGivenSomeNonNull() throws Exception {
        MyObject obj = new MyObject();

        String output = obj.someComplicatedCall("someArgValue");

        Assert.assertNotNullassertThat(output, notNullValue());
   }
}

3) Run your test class. In eclipse:

  1. Right click on the class name in the "Navigator" or "Package Explorer" view
  2. Select "Run As" ? -> JUnit TestA good example of a basic junit test (TODO: link to unit test in source)

Testing the OpenMRS API

(and other classes that use the OpenMRS Context object) To test a class that requires the Context object and its method calls, simply extend org.openmrs.test.BaseContextSensitiveTest. The BaseContextSensitiveTest class will run through the Spring setup to put the *Services into the Context object. This startup takes a few seconds, so when you can, create simple tests (see above) and do not call methods on Context.

1) Add an @should annotation to Identify the interface for the service interface you're testing:

Code Block
package org.openmrs.api;

**
* This service does blah blah blah...
*/
public classinterface MyService {

.......

**
* This method does something blah blah blah
* @param fname
* @param lname
* @return patients
*/
@should// getNB patientsthe giveninteresting validdetails firstare namein andthe last name
*/
implementation
public List<Patient> findPatient(String fname, String lname) throws Exception {     ...does something interesting here...   }
}

...

;

2) Create a test for this method:

Code Block
package org.openmrs.api;

import static org.hamcrest.CoreMatchers.hasSize;
import static org.junit.Assert.assertThat;

/**
 * Tests on the methods found in MyService
 */
public class MyServiceTest extends BaseContextSensitiveTest {

    /**
*  Check that output looks* rightSetup forrun thebefore shortall patientsof */our @Testtests
@Verifies(value = "should get patients given*/
valid first name and last@Before
name", method = "findPatients(String,String)") public void findPatients_shouldGetPatientsGivenValidFirstNameAndLastNamesetup() {
 throws Exception {     initializeInMemoryDatabase();
        executeDataSet("org/openmrs/test/api/myservice/include/patients.xml");
    authenticate();}

    ...

    /**
     * Check that output looks right for the short patients
     */
    @Test
    public void findPatients_shouldGetPatientsGivenValidFirstNameAndLastName() throws Exception {
        List<Patient> patients = Context.getPatientService().getPatients("John Doe", null, null, false);
        Assert.assertEqualsassertThat(5patients, patients.sizehasSize(5));
    }

...

}

3) Run your test class. In eclipse:

...

  1. Right click on the class name in the "Navigator" or "Package Explorer" view
  2. Select "Run As" ? > JUnit Test
  3. A good example of a Context sensitive junit test.

Setting up the expected database

By default, the Context is set up to run against an in-memory database called hsql h2. This database is automatically built from the hibernate Hibernate mapping files that Spring knows about.  

BaseContextSensitiveTest  classes will automatically load the initialInMemoryTestDataSet.xml and the standardTestDataset.xml, and you . You may use any object objects defined there for your tests. To insert a super user, call BaseContextSensitiveTest.initializeInMemoryDatabase(). This inserts the data in initialInMemoryTestDataSet.xml.

To authenticate your test to the Context object, call authenticated() . This will pop up a box asking the current user for an admin/password.

...

  • How can I authenticate to the Context without putting my username and password in the unit test code?
    Use the the authenticate()  method found in 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 .
  • Why am I getting the error org.openmrs.api.APIException: Service not found: interface org.openmrs.api ..... in my unit test?
    You're trying to use a basic unit test to do Context/API testing. Extend the org.openmrs.test.BaseContextSensitiveTest class.
  • Why am I getting the error: Already value [] for key [] bound to thread [main]?
    Your web unit test is probably extending BaseContextSensitiveTest intead of BaseWebContextSensitiveTest
  • Why am I getting the error: org.openmrs.api.APIException: contextDAO is null . . . in my unit test?
    Spring was not properly set up for OpenMRS. Try running a maven install on your local copy of OpenMRS (In Eclipse click run as, then select maven install).