Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "EclipseLink/Development/Testing/DBWS"
(→KeyMappingsTestSuite) |
|||
Line 46: | Line 46: | ||
The test code is in the (related) <code>xxxTestSuite</code> class - let's look at <code>KeyMappingsTestSuite</code>: | The test code is in the (related) <code>xxxTestSuite</code> class - let's look at <code>KeyMappingsTestSuite</code>: | ||
− | ====KeyMappingsTestSuite==== | + | ====<code>KeyMappingsTestSuite</code>==== |
<source lang="java5"> | <source lang="java5"> | ||
public class KeyMappingsTestSuite { | public class KeyMappingsTestSuite { | ||
Line 200: | Line 200: | ||
... | ... | ||
</source> | </source> | ||
+ | |||
====<code>RelationshipsTestSuite</code>==== | ====<code>RelationshipsTestSuite</code>==== | ||
Structured in a similar fashion to <code>KeyMappingsTestSuite</code>, <code>RelationshipsTestSuite</code> does not use a custom classloader that builds classes on the fly - the mapped domain classes actually exist. | Structured in a similar fashion to <code>KeyMappingsTestSuite</code>, <code>RelationshipsTestSuite</code> does not use a custom classloader that builds classes on the fly - the mapped domain classes actually exist. |
Revision as of 10:36, 24 March 2009
Contents
Summary
DBWS has a number of test suites, all written using JUnit4. This page outlines the various testsuites and the types of testing in each suite.
DBWS core tests
In the SVN repository under the DBWS component's high-level directory, there is a project eclipselink.dbws.test
This project contains test classes that test DBWS in its XRM mode - no Web service deployment artifacts, no container -
just a bridge between OXM and ORM projects:
\---trunk
| about.html
| ...
|
+---dbws
| +---eclipselink.dbws.test
| | | .classpath
| | | .project
| | | build.properties
| | | build.xml
| | |
| | +---etc
| | | dbsetup_keymappings.sql
| | | dbsetup_relationships.sql
| | | dbteardown_keymappings.sql
| | | dbteardown_relationships.sql
| | |
| | \---src
| | \---dbws
| | \---testing
| | | DBWSTestHelper.java
| | | RootHelper.java
| | |
| | +---keymappings
| | | KeyMappingsTestSuite.java
| | |
| | \---relationships
| | RelationshipsAddress.java
| | RelationshipsEmployee.java
| | RelationshipsPhone.java
| | RelationshipsTestSuite.java
The setup required to run these tests is running the appropriately named dbsetup_xxx.sql
script
(and conversely dbteardown_xxx.sql
-
where xxx
= keymappings
or relationships
).
The test code is in the (related) xxxTestSuite
class - let's look at KeyMappingsTestSuite
:
KeyMappingsTestSuite
public class KeyMappingsTestSuite { static final String KEYMAPPINGS_SCHEMA = "<?xml version='1.0' encoding='UTF-8'?>" + "<xsd:schema targetNamespace=\"urn:keymappings\" xmlns=\"urn:keymappings\" elementFormDefault=\"qualified\"\n" + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" + ">\n" + "<xsd:complexType name=\"phone\">\n" + ... static final String KEYMAPPINGS_DBWS = "<?xml version='1.0' encoding='UTF-8'?>\n" + "<dbws\n" + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + "xmlns:ns1=\"urn:keymappings\"\n" + ">\n" + "<name>keymappings</name>\n" + ... static final String KEYMAPPINGS_OR_PROJECT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<object-persistence version=\"" + CONSTANT_PROJECT_BUILD_VERSION + "\"\n" + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xmlns=\"http://www.eclipse.org/eclipselink/xsds/persistence\"\n" + " >\n" + "<name>keymappings</name>\n" + "<class-mapping-descriptors>\n" + "<class-mapping-descriptor xsi:type=\"relational-class-mapping-descriptor\">\n" + ... static final String KEYMAPPINGS_OX_PROJECT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<object-persistence version=\"" + CONSTANT_PROJECT_BUILD_VERSION + "\"\n" + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + "xmlns=\"http://www.eclipse.org/eclipselink/xsds/persistence\"\n" + ">\n" + "<name>keymappings</name>\n" + "<class-mapping-descriptors>\n" + "<class-mapping-descriptor xsi:type=\"xml-class-mapping-descriptor\">\n" + ... // test fixtures public static XMLComparer comparer = new XMLComparer(); public static XMLPlatform xmlPlatform = XMLPlatformFactory.getInstance().getXMLPlatform(); public static XMLParser xmlParser = xmlPlatform.newXMLParser(); public static XRServiceAdapter xrService = null; @BeforeClass public static void setUp() { final String username = System.getProperty(DATABASE_USERNAME_KEY); if (username == null) { fail("error retrieving database username"); }
Database connectivity
The setUp
method looks for the database connectivity information passed in as Java system properties:
Overriding behaviour
One of the notable things about this test class is the use of static Strings that contain all of the required XRM meta-data:
schema, ORM and OXM projects and the DBWS service descriptor file. For this test, these have been pre-built by hand and assembled
to follow the rules and styles of DBWS runtime processing. In fact, to be more accurate, these tests pre-date the existence of the
DBWSBuilder
utility (that knows the rules and styles of DBWS runtime processing and produces meta-data to match).
We can see the static JUnit4 test fixtures for this testsuite: OX helper objects that will be used for comparing XML documents and an
xrService
of type XRServiceAdapter
. The XRServiceAdapter
is a sub-class of
XRServiceModel
, the model object for the DBWS service descriptor
(fields: name
, session-name
and a Map<String, Operation>
of operations
). The XRServiceAdapter
object has additional fields: schemaNamespace
,
orSession
(built from the ORM project), oxSession
(built from the OXM project), xmlContext
(built from the OXM project), schema
and a
Map<QName, XMLDescriptor>
of descriptorsByQName
.
The XR service is built by an XRServiceFactory
thru the API public XRServiceAdapter buildService(XRServiceModel xrServiceModel)
:
XRServiceFactory factory = new XRServiceFactory() { @Override public XRServiceAdapter buildService(XRServiceModel xrServiceModel) { parentClassLoader = this.getClass().getClassLoader(); xrSchemaStream = new ByteArrayInputStream(KEYMAPPINGS_SCHEMA.getBytes()); return super.buildService(xrServiceModel); } ... }; XMLContext context = new XMLContext(new DBWSModelProject()); XMLUnmarshaller unmarshaller = context.createUnmarshaller(); DBWSModel model = (DBWSModel)unmarshaller.unmarshal(new StringReader(KEYMAPPINGS_DBWS)); xrService = factory.buildService(model);
The buildService
method is overridden in the anonymous inner-class XRServiceFactory(){}
because normally a
XRServiceFactory
looks for the
XRM meta-data artifacts in archive files (.jar, .war) on the classpath. In this case, the 'files' exist in-memory and can be directly built without doing
any classloader resource lookups (NB - the buildSessions
method is overridden for the same reason - the OXM and ORM projects exist in-memory).
Invoking a DBWS operation
In the method getAllEmployees
we can see how a DBWS query operation
is invoked - an Invocation
object is built with the same name as a
DBWS query operation
described in the DBWS service descriptor file. Parameters
may be added (in this specific case - get all employees - none are required)
and the xrService
is used to execute the Invocation
Invocation invocation = new Invocation("getAllEmployees"); Operation op = xrService.getOperation(invocation.getName()); Object result = op.invoke(xrService, invocation);
The operation
in this case returns a collection; thus, the result
object must be cast to a Vector
and
each object marshalled to an XML document.
When the OR and OX projects were read in, a custom classloader builds any non-existent project model classes on-the-fly.
BaseEntityClassLoader becl = new BaseEntityClassLoader(parentClassLoader); XMLContext context = new XMLContext( new EclipseLinkObjectPersistenceRuntimeXMLProject(), becl); XMLUnmarshaller unmarshaller = context.createUnmarshaller(); Project orProject = (Project)unmarshaller.unmarshal( new StringReader(KEYMAPPINGS_OR_PROJECT));
Thus, the objects in the result
Vector are all sub-classes of o.e.p.internal.dynamicpersist.BaseEntity
for (BaseEntity employee : resultVector) { rootHelper.roots.add(employee); rootHelper.roots.add(employee.get(0)); // address Vector<BaseEntity> phones = (Vector<BaseEntity>)employee.get(4); // phones phones.size(); // trigger IndirectList for (BaseEntity phone : phones) { rootHelper.roots.add(phone); } } Document doc = xmlPlatform.createDocument(); XMLMarshaller marshaller = xrService.getXMLContext().createMarshaller(); marshaller.marshal(rootHelper, doc);
In the OR-world, there is no problem with returning a graph of related or un-related classes in a single Vector. However, in the OX world,
a document requires a
root element. Thus in the KEYMAPPINGS_OX_PROJECT
there is a mapping for a helper class
dbws.testing.RootHelper
that uses the XMLAnyCollectionMapping
to allow either an Employee, or Address or Phone to be nested under the <employee-address-phone-system>
element.
Once the rootHelper
is populated,
the xrService
is used to marshall it to an XML document. Finally, the test fixtures xmlParser
and
comparer
are used to indicate if the generated document
is the same as an expected control document:
Document controlDoc = xmlParser.parse(new StringReader(EMPLOYEE_COLLECTION_XML)); assertTrue("control document not same as XRService instance document", comparer.isNodeEqual(controlDoc, doc)); ... public static final String EMPLOYEE_COLLECTION_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<employee-address-phone-system xmlns=\"urn:keymappings\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<employee address-ref-id=\"1\" employee-id=\"1\">" + "<first-name>Mike</first-name>" + "<last-name>Norman</last-name>" + "<phones>" + "<phone-ref phone-id=\"1\"/>" + "<phone-ref phone-id=\"2\"/>" + "</phones>" + ...
RelationshipsTestSuite
Structured in a similar fashion to KeyMappingsTestSuite
, RelationshipsTestSuite
does not use a custom classloader that builds classes on the fly - the mapped domain classes actually exist.