This article provides a quick overview of JUnit integration JDeveloper 11g

  Main Topics

  Extra Topics



Verify the JUnit Extension in JDeveloper

    JUnit functionality is an optional extension to JDeveloper 11g
    So the first step is to verify the extension is installed.
    Start JDeveloper and from the main menu choose Help->About
    Select the Extensions tab and verify JUnit is listed.
    Confirm JUnit Integration listed.
    If its not listed, add it by choosing Help->Check For Updates
    and select JUnit from the available updates.
    After installation restart JDeveloper


Create a parallel source directory for tests (Optional)

    Test Classes should be located in the same java package as the classes they test.
    But it may be undesirable to mix the test and target classes in deployment units and version control.
    One solution is to create a parallel source hierchy so that the same java packages exist under two different directories.

    Follow these steps:
            Right click on a Java Project in JDeveloper and choose Project Properties.
            In the Project Properties dialog, select the Project Source Paths node.
            The Project Source paths field will indicate the current source path for the project
                For example c:\projects\myApp\JavaProject\src
            Create a new directory in the file system outside JDeveloper named c:\projects\myApp\JavaProject\test


            File_Explorer


        Return to the JDeveloper Project Properties dialog and click the Add button to add an additional source path to the project. 
        Add the path to the newly created directory.
        Click the up button to move the new test folder to the first entry in the list.

        Note: The order of the directories in the list is important.  When new Java Classes for this project are created they will be placed in
        the directory named indicated by the top entry in the list.  The current setting is correct for creating Test Case classes.
        Change the order of the list to have the src folder first when creating Classes that are not used for testing.

     
        The final configuration should appear as below
         Project_Properties

        In the JDeveloper Application explorer the files in both the src and test directories will be displayed in a single hiearchy


         Application_Explorer_Showing_single_Source_tree




Adding a JUnit Test Case to the Java Project


     Right click on the Java Project in the Application Navigator and choose New.
     In the Gallery Dialog choose the All Technologies Tab
     Expand the General Category and select Unit Tests
     Select the Test Case item and press the OK button.

       New_Gallery_Dialog

    The Create Test Case wizard should appear.
    In Step one, click the Browse button and navigate to the java package containing the Class to be tested.

     New_Test_Case_Class_Selection
    Check the Classes and methods that will be tested by the new Test Case.
    Press the Next Button

    Test_Case_Wizard

     In Step 2 set a name for the new Test Class and set the package.
     Select the setUp() and tearDown() methods.

     Create_Test_Case_Wizard_Step_2

     In Step 3 press the finish button.

     (Optional note regarding Test Fixtures)
     This dialog also supports the selection of an existing Test Fixture Class.
     A Test Fixture is a JUnit class that creates test data to be shared between a number of test classes.
     If a Fixture is desirable, create Fixture before the Test Class by right clicking on the Java Project,
     choose New,  then in the Gallery Dialog choose Test Case and press the OK button.
   

      New_Test_Case_Step_3

    
     Note:  If compile errors occur for Junit classes, add the JUnit library to the Project as follows.:
                Right click on the Java Project and Choose Project Properties
                In the left side of the Project Properties window select "Libraries and Classpath"
                On the right side press the Choose Library button,
                Select the "JUnit 4 Runtime" library in the Extension catagory and press the OK button.

                 Add_Library



Implementing a Test Case

   There are a lot of good tutorials on the web that cover JUnit.

   Below is an example of a Test Class
 
package com.example.reusable.asset;

import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathFunctionException;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;


/*
* JUnit 4 Example
* With JUnit 4 Test methods use @Test annotation and to no longer need to end with the word test
* and the Test Class no longer needs to extend TestCase
* This simple example uses the local setup() and teardown() methods rather than using a TestFixture class
*/

public class SortEmployeesTest {

Document doc1 = null;
Document doc2 = null;
Document doc3 = null;

String xmlString1 = "" +
"";

String xmlString2 = "" +
"" +
"
";

String xmlString3 = "" +
"" +
"" +
"190" +
"Bob" +
"Jones" +
"Accountant" +
"" +
"109" +
"
" +
"" +
"100" +
"Peter" +
"Baines" +
"President" +
"" +
"102" +
"
" +
"" +
"120" +
"James" +
"Last" +
"Service Advisor" +
"" +
"" +
"
" +
"
";


public SortEmployeesTest() {
}


@Before
public void setUp() throws Exception {

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = null;

builder = factory.newDocumentBuilder();

// Create empty doc
InputSource iSource1 = new InputSource( new StringReader(xmlString1));
doc1 = builder.parse(iSource1);

// create no employees doc
InputSource iSource2 = new InputSource( new StringReader(xmlString2));
doc2 = builder.parse(iSource2);

// create full doc
InputSource iSource3 = new InputSource( new StringReader(xmlString3));
doc3 = builder.parse(iSource3);

}

@After
public void tearDown() throws Exception {
}


/**
* Test with Wrong document type, expect exception
* @see SortEmployees#sortNodes(org.w3c.dom.Node,boolean)
*/
@Test
public void testWrongInputDocumentType() {
try {
SortEmployees.sortNodes(doc1.getFirstChild(), false);
fail("sortNodes() accepted an invalid document type");
printDocument(doc1);
} catch (XPathFunctionException ex) {
assertTrue(true);
}
}


/**
* Test Document with no Employees
* @see SortEmployees#sortNodes(org.w3c.dom.Node,boolean)
*/
@Test
public void testNoEmployees() {
try {
SortEmployees.sortNodes(doc2.getFirstChild(), false);
assertEquals("Found wrong number of Employees after sort. ", 0,
doc2.getFirstChild().getChildNodes().getLength());

} catch (XPathFunctionException ex) {
fail("sortEmployees() threw exception processing document with no employees");
ex.printStackTrace(System.out);
printDocument(doc2);

}
}


/**
* Test with Valid Document
* @see SortEmployees#sortNodes(org.w3c.dom.Node,boolean)
*/
@Test
public void testValidDocument() {
try {
Node employees = doc3.getFirstChild();
SortEmployees.sortNodes(doc3.getFirstChild(), false);

// Total Employees
assertEquals("Found wrong number of Employees after sort. ", 3,
employees.getChildNodes().getLength());

// System.out.println(employees.getFirstChild().getTextContent());
// System.out.println(employees.getFirstChild().getNextSibling().getTextContent());

// Employee 1 Dept expecting ""
assertEquals("Employees in wrong order after sort. ", "",
employees.getFirstChild().getLastChild().getTextContent());

// Employee 24 Dept expecting 102
assertEquals("Employees in wrong order after sort. ", "102",
employees.getFirstChild().getNextSibling().getLastChild().getTextContent());

// Employee 3 Dept expecting 109
assertEquals("Employees in wrong order after sort. ", "109",
employees.getFirstChild().getNextSibling().getNextSibling().getLastChild().getTextContent());


printDocument(doc3);

} catch (XPathFunctionException ex) {
fail("sortEmployees() threw exception processing valid document");
ex.printStackTrace(System.out);
printDocument(doc3);
}
}

public void printDocument(Document doc) {
// Print the Node to Stdout
try {
javax.xml.transform.TransformerFactory tfactory = TransformerFactory.newInstance();
javax.xml.transform.Transformer xform = tfactory.newTransformer();
xform.setOutputProperty(OutputKeys.INDENT, "yes");
// xform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

javax.xml.transform.Source src= new DOMSource(doc);
java.io.StringWriter writer = new StringWriter();
Result result = new StreamResult(writer);
xform.transform(src, result);
System.out.println(writer.toString());
}
catch (TransformerConfigurationException tc) {
System.out.println("printDocument: Unable to ouput document");
tc.printStackTrace (System.out);
}

catch (TransformerException te) {
System.out.println("printDocument: Unable to ouput document");
te.printStackTrace (System.out);
}

}



}


   Here is the Class to be tested

 
package com.example.reusable.asset;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import javax.xml.xpath.XPathFunctionException;
import oracle.fabric.common.xml.xpath.IXPathContext;
import oracle.fabric.common.xml.xpath.IXPathFunction;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/** Mapper function that can be used by any SOA Suite component.
*
**/

public class SortEmployees implements IXPathFunction {

public Object call(IXPathContext context, List args) {

org.w3c.dom.Node employees = (Node) args.get(0);
System.out.println("SortEmployees Retrieved employees ");
try {

sortNodes(employees, false);
}
catch (XPathFunctionException ex)
{
System.err.println("Error: SortEmployees XPath function exception, skipped processing: " +
ex.getMessage());
employees = (Node) args.get(0);
}

return employees;
}

/**
* Sorts the nodes in a node list
*
* @param nodeList - list whose nodes will be sorted
* @param descending - true for sorting in descending order
*/
public static Node sortNodes(Node inputNode, boolean descending) throws XPathFunctionException {


List nodes = new ArrayList();

if(inputNode==null) {
throw new XPathFunctionException("Input Node is null");
}
else {
if(inputNode == null)
throw new XPathFunctionException("Expected input Node of type http://www.example.org : Employees " +
"received null document");
if(inputNode.getNamespaceURI() == null ||
!(inputNode.getNamespaceURI().equals("http://www.example.org")) ||
!inputNode.getLocalName().equals("Employees") )
throw new XPathFunctionException("Expected input Node of type http://www.example.org : Employees " +
"received " + inputNode.getNamespaceURI() + " : " + inputNode.getLocalName());

NodeList employees = inputNode.getChildNodes();
// System.out.println("Found " + employees.getLength() + " Employees");

if (employees.getLength() > 0) {
for (int i = 0; i < employees.getLength(); i++) {
Node tNode = employees.item(i);
nodes.add(tNode);
}

Comparator comp = new EmpDeptComparator();

if (descending)
{
//if descending is true, get the reverse ordered comparator
Collections.sort(nodes, Collections.reverseOrder(comp));
} else {
Collections.sort(nodes, comp);
}

for (Iterator iter = nodes.iterator(); iter.hasNext();) {
Node element = (Node) iter.next();
inputNode.appendChild(element);
}
}
}

return inputNode;

}
}

class EmpDeptComparator implements Comparator {

public int compare(Object arg0, Object arg1) {
return ((Node) arg0).getFirstChild().getTextContent().compareTo(
((Node) arg1).getLastChild().getTextContent());
}

}

Running the JUnit Test Cases

   Tests can be run from within JDeveloper without creating a JUnit Test Suite.
   Simply right click on the Java Project containing the Tests and choose

   Starting_Tests_From_Junit


Test Results are shown in the  JUnit Test Runner Window as shown

Test_Summary



  JUnit 4 Test Suite Class (Optional)

   The following test Suite class is not required if tests are run solely within JDeveloper.
   The class does support running the tests from the Java Command line or Ant

 
package com.example.reusable.asset;

import org.junit.runner.JUnitCore;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

/*
* JUnit 4 Test Suite
* List Test cases as comma seperated list in @Suite.SuiteClasses annotation
* Right click and choose run within JDeveloper
* Or run from java command line or Ant using main method
*
* This class is not necessary if testing solely within JDeveloper
*/
@RunWith(Suite.class)
@Suite.SuiteClasses( { com.example.reusable.asset.SortEmployeesTest.class })
public class AllTestsSuite {

public static void main(String[] args) {
JUnitCore.runClasses(new Class[] { AllTestsSuite.class });
}

}



JUnit Test Fixture Example  (Optional)

   A test fixture centralizes the creation of test data to be used by multiple Test Classes or Developers of different Test Classes

   Following is the example from above modified to use a Test Fixture

   Test Fixture Class:
 
package com.example.reusable.asset;

import java.io.IOException;
import java.io.StringReader;

import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class UnitTestFixture {


Document doc1 = null;
Document doc2 = null;
Document doc3 = null;

String xmlString1 = "" +
"";

String xmlString2 = "" +
"" +
"
";

String xmlString3 = "" +
"" +
"" +
"190" +
"Bob" +
"Jones" +
"Accountant" +
"" +
"109" +
"
" +
"" +
"100" +
"Peter" +
"Baines" +
"President" +
"" +
"102" +
"
" +
"" +
"120" +
"James" +
"Last" +
"Service Advisor" +
"" +
"" +
"
" +
"
";



public UnitTestFixture() {


}

public void setUp() throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = null;

builder = factory.newDocumentBuilder();

// Create empty doc
InputSource iSource1 = new InputSource( new StringReader(xmlString1));
doc1 = builder.parse(iSource1);

// create no employees doc
InputSource iSource2 = new InputSource( new StringReader(xmlString2));
doc2 = builder.parse(iSource2);

// create full doc
InputSource iSource3 = new InputSource( new StringReader(xmlString3));
doc3 = builder.parse(iSource3);

}

public void tearDown() {
}


public void printDocument(Document doc) {
// Output the modified Node
try {
javax.xml.transform.TransformerFactory tfactory = TransformerFactory.newInstance();
javax.xml.transform.Transformer xform = tfactory.newTransformer();
xform.setOutputProperty(OutputKeys.INDENT, "yes");
// xform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

javax.xml.transform.Source src= new DOMSource(doc);

java.io.StringWriter writer = new StringWriter();
Result result = new StreamResult(writer);

xform.transform(src, result);
System.out.println(writer.toString());
}
catch (TransformerConfigurationException tc) {
System.out.println("printDocument: Unable to ouput document");
tc.printStackTrace (System.out);
}

catch (TransformerException te) {
System.out.println("printDocument: Unable to ouput document");
te.printStackTrace (System.out);
}

}

public Document getDoc1() {
return doc1;
}

public Document getDoc2() {
return doc2;
}

public Document getDoc3() {
return doc3;
}
}


   Test Class using Fixture:
package com.example.reusable.asset;

import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathFunctionException;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;


/*
* JUnit 4 Example
* With JUnit 4 Test methods use @Test annotation and to no longer need to end with the word test
* and the Test Class no longer needs to extend TestCase
*/

public class SortEmployeesTestUsingFixture {


UnitTestFixture fixture1 = new UnitTestFixture();

public SortEmployeesTestUsingFixture() {
}

@Before
public void setUp() throws Exception {
fixture1.setUp();
}

@After
public void tearDown() throws Exception {
fixture1.tearDown();
}


/**
* Test with Wrong document type, expect exception
* @see SortEmployees#sortNodes(org.w3c.dom.Node,boolean)
*/
@Test
public void testWrongInputDocumentType() {
try {
SortEmployees.sortNodes(fixture1.getDoc1().getFirstChild(), false);
fail("sortNodes() accepted an invalid document type");
fixture1.printDocument(fixture1.getDoc1());
} catch (XPathFunctionException ex) {
assertTrue(true);
}
}


/**
* Test Document with no Employees
* @see SortEmployees#sortNodes(org.w3c.dom.Node,boolean)
*/
@Test
public void testNoEmployees() {
try {
SortEmployees.sortNodes(fixture1.getDoc2().getFirstChild(), false);
assertEquals("Found wrong number of Employees after sort. ", 0,
fixture1.getDoc2().getFirstChild().getChildNodes().getLength());

} catch (XPathFunctionException ex) {
fail("sortEmployees() threw exception processing document with no employees");
ex.printStackTrace(System.out);
fixture1.printDocument(fixture1.getDoc2());

}
}


/**
* Test with Valid Document
* @see SortEmployees#sortNodes(org.w3c.dom.Node,boolean)
*/
@Test
public void testValidDocument() {
try {
Node employees = fixture1.getDoc3().getFirstChild();
SortEmployees.sortNodes(fixture1.getDoc3().getFirstChild(), false);

// Total Employees
assertEquals("Found wrong number of Employees after sort. ", 3,
employees.getChildNodes().getLength());

// System.out.println(employees.getFirstChild().getTextContent());
// System.out.println(employees.getFirstChild().getNextSibling().getTextContent());

// Employee 1 Dept expecting ""
assertEquals("Employees in wrong order after sort. ", "",
employees.getFirstChild().getLastChild().getTextContent());

// Employee 24 Dept expecting 102
assertEquals("Employees in wrong order after sort. ", "102",
employees.getFirstChild().getNextSibling().getLastChild().getTextContent());

// Employee 3 Dept expecting 109
assertEquals("Employees in wrong order after sort. ", "109",
employees.getFirstChild().getNextSibling().getNextSibling().getLastChild().getTextContent());


fixture1.printDocument(fixture1.getDoc3());

} catch (XPathFunctionException ex) {
fail("sortEmployees() threw exception processing valid document");
ex.printStackTrace(System.out);
fixture1.printDocument(fixture1.getDoc3());
}
}
}







Download the complete example as a zip file from GitHub  Here