Versions Compared

Key

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

We like tests. We use JUnit and Mockito (and, sometimes, reluctantly, PowerMockito.) HTTP Integration tests use grizzly.

Ensuring that the quality of the code base is maintained (as it is extended, refactored, or otherwise modified) can be addressed through the extensive coverage of functionality by unit or integration testing.  One approach often undertaken within the domain of software development is that of test driven development, in which the appropriate testing suites outlining the behavior of some method are structured concurrently or before the method itself is actually implemented.  Adhering to this methodology is by no means mandatory, but it does often assist in ensuring that the code base is quality assured to a higher degree.

Writing tests

Unit Tests

Each module has unit tests in the src/test/java/org/fcrepo/ directory and integration tests in the src/test/java/org/fcrepo/integration/ directory.

The unit tests often use mock objects to create surrogates for the Modeshape and webapp machinery that much of the Fedora code interacts with.  Some good examples of mock object usage are in the fcrepo-http-api module (e.g., FedoraNodesTest.java) and in the fcrepo-jms-indexer-core module (e.g. IndexerGroupTest.java). By convention, unit test classes are named as: <FunctionalClass>Test.java

Examples

Code Block
languagejava
titlefcrepo-kernel/src/test/java/org/fcrepo/kernel/observer/FedoraEventTest.java
firstline114
linenumberstrue
collapsetrue
@Test

    public void testAddType() {

        e.addType(PROPERTY_CHANGED);

        assertEquals(2, e.getTypes().size());




        assertTrue("Should contain: " + PROPERTY_CHANGED, contains(e.getTypes().iterator(), PROPERTY_CHANGED));

        assertTrue("Should contain: 1", contains(e.getTypes().iterator(), 1));

    }




    @Test

    public void testAddProperty() {

	e.addProperty("prop");

        assertEquals(1, e.getProperties().size());

        assertEquals("prop", e.getProperties().iterator().next());

    }




    @Test

    public void testToString() throws RepositoryException {

        final String text = e.toString();

        assertTrue("Should contain path: " + text, text.contains(e.getPath()));

        assertTrue("Should contain info: " + text, text.contains(e.getInfo().toString()));




        assertTrue("Should contain types: " + text, text.contains(Integer.toString(e.getTypes().iterator().next())));

        assertTrue("Should contain date: " + text, text.contains(Long.toString(e.getDate())));




        assertFalse("Should not contain user-data: " + text, text.contains(e.getUserData()));

        assertFalse("Should not contain user-id: " + text, text.contains(e.getUserID()));

    }
Code Block
languagejava
titlefcrepo-http-api/src/test/java/org/fcrepo/http/api/FedoraNodesTest.java
firstline159
linenumberstrue
collapsetrue
    @Test

    public void testCopyObject() throws RepositoryException, URISyntaxException {




        final ValueFactory mockVF = mock(ValueFactory.class);

	when(mockSession.getValueFactory()).thenReturn(mockVF);

        when(mockNodes.exists(mockSession, path)).thenReturn(true);

	when(mockContainer.getPath()).thenReturn(path);




        testObj.copyObject("http://localhost/fcrepo/bar");

	verify(mockNodes).copyObject(mockSession, path, "/bar");

    }




    @Test(expected = ClientErrorException.class)

    public void testCopyMissingObject() throws RepositoryException, URISyntaxException {




        final ValueFactory mockVF = mock(ValueFactory.class);

        when(mockSession.getValueFactory()).thenReturn(mockVF);

	when(mockNodes.exists(mockSession, path)).thenReturn(false);




	testObj.copyObject("http://localhost/fcrepo/bar");

    }




    @Test(expected = ServerErrorException.class)

    public void testCopyObjectWithBadDestination() throws RepositoryException, URISyntaxException {

        final ValueFactory mockVF = mock(ValueFactory.class);

        when(mockSession.getValueFactory()).thenReturn(mockVF);

	when(mockNodes.exists(mockSession, path)).thenReturn(true);




        testObj.copyObject("http://somewhere/else/baz");




    }

Integration Tests

Integration tests use embedded Modeshape, servlet engine, etc. to run real requests against the code.  The web-based tests typically use HttpClient to make requests.  Non-web tests, use injection to have the repository and service objects made accessible to the tests (the embedded repository and injection are configured in the src/test/resources directory).  Some good examples are in the fcrepo-http-api module (e.g. FedoraNodesIT.java) and fcrepo-kernel module (e.g., FedoraResourceImplIT.java). By convention, integration test classes are named as: <FunctionalClass>IT.java

Examples

Code Block
languagejava
titlefcrepo-http-api/src/test/java/org/fcrepo/integration/http/api/FedoraNodesIT.java
firstline53
linenumberstrue
collapsetrue
    @Test
    public void testCopy() throws Exception {
        final HttpResponse response  = createObject("");
        final String pid = getRandomUniquePid();
        final String location = response.getFirstHeader("Location").getValue();
        final HttpCopy request = new HttpCopy(location);
        request.addHeader("Destination", serverAddress + pid);
        client.execute(request);

        final HttpGet httpGet = new HttpGet(serverAddress + pid);

        final HttpResponse copiedResult = client.execute(httpGet);
        assertEquals(OK.getStatusCode(), copiedResult.getStatusLine().getStatusCode());

        final HttpResponse originalResult = client.execute(new HttpGet(location));
        assertEquals(OK.getStatusCode(), originalResult.getStatusLine().getStatusCode());
    }

    @Test
    public void testCopyDestExists() throws Exception {
        final HttpResponse response1 = createObject("");
        final String location1 = response1.getFirstHeader("Location").getValue();
        final HttpResponse response2 = createObject("");
        final String location2 = response2.getFirstHeader("Location").getValue();

        final HttpCopy request = new HttpCopy(location1);
        request.addHeader("Destination", location2);
        final HttpResponse result = client.execute(request);
        assertEquals(PRECONDITION_FAILED.getStatusCode(), result.getStatusLine().getStatusCode());
    }
Code Block
languagejava
titlefcrepo-auth-common/src/test/java/org/fcrepo/auth/integration/FedoraResponseCodesIT.java
firstline36
linenumberstrue
collapsetrue
    @Test
    public void testAllowedAddDatastream() throws Exception {
        final String pid = getRandomUniquePid() + "Permit";
        final HttpPut objMethod = putObjMethod(pid);
        assertEquals(201, getStatus(objMethod));

        final HttpPost method = postDSMethod(pid, "zxcpermit", "foo");
        final HttpResponse response = client.execute(method);
        final String location = response.getFirstHeader("Location").getValue();
        assertEquals(201, response.getStatusLine().getStatusCode());
        assertEquals("Got wrong URI in Location header for datastream creation!", serverAddress + pid +
            "/zxcpermit/jcr:content", location);
    }

    @Test
    public void testDeniedAddDatastream() throws Exception {
        final String pid = getRandomUniquePid() + "Permit";
        final HttpPut objMethod = putObjMethod(pid);

        assertEquals(201, getStatus(objMethod));

        final HttpPut obj2Method = putObjMethod(pid + "/FedoraDatastreamsTest2Deny");
        assertEquals(201, getStatus(obj2Method));

        final HttpPost method = postDSMethod(pid + "/FedoraDatastreamsTest2Deny", "zxc", "foo");
        final HttpResponse response = client.execute(method);
        assertEquals(403, response.getStatusLine().getStatusCode());
    }

 

Remember to follow the Code Style Guide when writing your test classes. This is especially true if writing a test class is your first foray into contributing to Fedora.

Running the tests

Code Block
$ mvn test verify

 

See the fcrepo4 README file for more detailed instructions concerning Maven settings, etc., to build from source.