Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  •  Integration Tests must be written for any methods/classes which require database access to test.  We feel integration tests are more important than unit tests (and you'll see this in our codebase).
  •  Unit Tests must be written for any (public or private) methods/classes which don't require database-level access to test.  For example, a utility method that parses a string should have a unit test that proves the string parsing works as expected.
  •  Include tests for different user types to prove access permissions are working. This includes testing as (1) an Anonymous user, (2) an Authenticated User (non-Admin), (3) an Administrator and/or Community/Collection Admin (as necessary).
  •  Include tests for known error scenarios & error codes.  If the code throws an exception or returns an 4xx response, then a test should prove that is working.
  •  Bug fix PRs should include a test that reproduces the bug to prove it is fixed.  For clarity, it may be useful to provide the test in a separate commit from the bug fix.
  •  Every test method must cleanup any test data createdSee guidelines below for "Cleaning up test data".
  •  Use "context.turnOffAuthorisationSystem()" sparingly, and always follow-up  with a "context.restoreAuthSystemState()" as soon as possible (and in the same test method).  As turning off the authorization system can affect the behavior of tests, only use these methods when you need to create or delete test data.
  •  If a test needs to temporarily modify a configuration's value (in any *.cfg file), see the guidelines below for "Changing configuration properties in tests"

Writing Integration Tests

...

  1. Use Builders for automatic cleanup: Whenever possible, use the Builder test classes (see org.dspace.app.rest.builder.*) in "dpace-server-webapp", as these Builder classes automatically cleanup after themselves!

    Code Block
    // Example of creating a test Item via the ItemBuilder class
    // As soon as the method using this "testItem" completes, the "testItem" will be automatically deleted
    // by the AbstractBuilderCleanupUtil (which is called @After every test)
    context.turnOffAuthorisationSystem();
    Item testItem = ItemBuilder.createItem(context, collection);
    context.restoreAuthSystemState();


  2. Cleanup after test POST or file upload: If you are testing a POST command (or file upload), you MUST cleanup the POSTed data by parsing the ID out of the response and using a Builder class for cleanup.  Our best practice is to use the following code logic.  Further examples can be found in the codebase.

    Code Block
    languagejava
    import static com.jayway.jsonpath.JsonPath.read;
    import java.util.concurrent.atomic.AtomicReference;
    
    AtomicReference<UUID> idRef = new AtomicReference<>();
    try {
        // Example of a POST command to create a new Collection while logged in as the user with the given "authToken"
        getClient(authToken).perform(post("/api/core/collections")
                            ...[various params and data sent via POST]...
    
                            // Check the POST was successful, which means we created test content & need to clean it up!
                            .andExpect(status().isCreated())
    
                            // From the JSON response, read the "id" field, parse it as a UUID, and save to "idRef" local variable.
                            .andDo(result -> idRef.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));
    } finally {
        // Using the CollectionBuilder, delete the Collection with UUID equal to value of idRef
        CollectionBuilder.deleteCollection(idRef.get());
    }


  3. (If neither of the above are possible) "Manually" delete created data: If you create test data in the "dspace-api", unfortunately, you must manually cleanup after yourself at this time.  The "dspace-api" module doesn't have automatic cleanup utilities as described above.  Here's an example of doing so:

    Code Block
    // Create test data by temporarily turning off authorization
    context.turnOffAuthorisationSystem();
    WorkspaceItem workspaceItem = workspaceItemService.create(context, collection, true);
    Item item = installItemService.installItem(context, workspaceItem);
    context.restoreAuthSystemState();
    
    [perform various tests]
    
    // Delete the test Item created, again by temporarily turning off authorization
    context.turnOffAuthorisationSystem();
    itemService.delete(context, item);
    context.restoreAuthSystemState();


Changing configuration

...

properties in tests

The DSpace ConfigurationService makes this very easy to do! 

All you have to do is call setProperty  in your test to change the value to whatever value your test needs or expects, for example:

Code Block
// Change the value of the "dspace.ui.url" to be "http://mydspace.edu"
configurationService.setProperty("dspace.ui.url", "http://mydspace.edu");

// Any tests after the thisabove call thatwill usesee "dspace.ui.url = http://mydspace.edu"
// NOTE: once the test method completes, our test environment will find automatically reset "dspace.ui.url" back to the newdefault value.

NOTE: You do NOT need to reset the property value back to the default setting.  After every test runs, the ConfigurationService reloads the defaults from the dspace.cfg  and the local.cfg  used by our test environment.

...