You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2021/01/27 19:59:47 UTC

[uima-uimaj] 01/01: [UIMA-6308] Refactor unit tests

This is an automated email from the ASF dual-hosted git repository.

rec pushed a commit to branch UIMA-6308-Refactor-unit-tests
in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git

commit 1cfbe0cd459142869cdaa560d59c980cdb07f70c
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Mon Jan 25 18:08:01 2021 +0100

    [UIMA-6308] Refactor unit tests
    
    - Upgraded MetaDataObject_implTest
    - Upgraded TypeSystemDescription_implTest
    - Upgrade AnalysisEngineDescription_impltTest
    - Added PrintExceptionsWhenRunFromCommandLineRule as a replacement for JUnitExtension.handleException(e) in try/catch around tests
---
 .../impl/AnalysisEngineDescription_implTest.java   | 880 ++++++++++-----------
 .../metadata/impl/MetaDataObject_implTest.java     | 362 ++++-----
 .../impl/TypeSystemDescription_implTest.java       | 296 +++----
 .../PrintExceptionsWhenRunFromCommandLineRule.java |  46 ++
 4 files changed, 777 insertions(+), 807 deletions(-)

diff --git a/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java b/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java
index ec06f85..8290873 100644
--- a/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java
+++ b/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java
@@ -16,9 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.uima.analysis_engine.impl;
 
+import static org.apache.uima.UIMAFramework.newDefaultResourceManager;
+import static org.apache.uima.resource.ResourceInitializationException.UNDEFINED_KEY_IN_FLOW;
+import static org.apache.uima.test.junit_extension.JUnitExtension.getFile;
+import static org.apache.uima.util.CasCreationUtils.createCas;
+import static org.assertj.core.api.Assertions.as;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
@@ -28,9 +35,6 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Random;
 
-import org.junit.Assert;
-import junit.framework.TestCase;
-
 import org.apache.uima.Constants;
 import org.apache.uima.ResourceSpecifierFactory;
 import org.apache.uima.UIMAFramework;
@@ -84,580 +88,538 @@ import org.apache.uima.resource.metadata.impl.NameValuePair_impl;
 import org.apache.uima.resource.metadata.impl.TypePriorities_impl;
 import org.apache.uima.resource.metadata.impl.TypeSystemDescription_impl;
 import org.apache.uima.test.junit_extension.JUnitExtension;
-import org.apache.uima.util.CasCreationUtils;
+import org.apache.uima.test.junit_extension.PrintExceptionsWhenRunFromCommandLineRule;
 import org.apache.uima.util.InvalidXMLException;
 import org.apache.uima.util.Logger;
 import org.apache.uima.util.XMLInputSource;
 import org.apache.uima.util.XMLParser;
+import org.apache.uima.util.XMLizable;
+import org.assertj.core.api.InstanceOfAssertFactories;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.xml.sax.SAXException;
 
 /**
  * Test the AnalysisEngineDescription_impl class.
- * 
  */
-public class AnalysisEngineDescription_implTest extends TestCase {
+public class AnalysisEngineDescription_implTest {
+
+  public @Rule TestRule exceptingHandlingRule = new PrintExceptionsWhenRunFromCommandLineRule();
 
   // Text encoding to use for the various byte/character conversions happening in this test case.
   // Public because also used by other test cases.
   public static final String encoding = "utf-8";
-  
+
   private static final File TEST_DATA_FILE = JUnitExtension
       .getFile("ResourceTest/ResourceManager_implTest_tempDataFile.dat");
-  
-  private AnalysisEngineDescription primitiveDesc;
 
+  private XMLParser xmlParser;
+  private AnalysisEngineDescription primitiveDesc;
   private AnalysisEngineDescription aggregateDesc;
-  
-  /**
-   * Constructor for AnalysisEngineDescription_implTest.
-   * 
-   * @param arg0
-   */
-  public AnalysisEngineDescription_implTest(String arg0) {
-    super(arg0);
-  }
 
-  /**
-   * @see TestCase#setUp()
-   */
-  @Override
-  protected void setUp() throws Exception {
-    try {
-      super.setUp();
-      UIMAFramework.getXMLParser().enableSchemaValidation(true);
-      
-      TypeSystemDescription typeSystem = new TypeSystemDescription_impl();
-      TypeDescription type1 = typeSystem.addType("Fake", "<b>Fake</b> Type", "Annotation");
-      type1.addFeature("TestFeature", "For Testing Only",
-              CAS.TYPE_NAME_STRING);
-      TypeDescription enumType = typeSystem.addType("EnumType", "Test Enumerated Type",
-              "uima.cas.String");
-      enumType.setAllowedValues(new AllowedValue[] { new AllowedValue_impl("One", "First Value"),
-          new AllowedValue_impl("Two", "Second Value") });
-
-      TypePriorities typePriorities = new TypePriorities_impl();
-      TypePriorityList priorityList = typePriorities.addPriorityList();
-      priorityList.addType("Fake");
-      priorityList.addType("EnumType");
-
-      FsIndexDescription index = new FsIndexDescription_impl();
-      index.setLabel("testIndex");
-      index.setTypeName("Fake");
-      FsIndexKeyDescription key1 = new FsIndexKeyDescription_impl();
-      key1.setFeatureName("TestFeature");
-      key1.setComparator(1);
-      FsIndexKeyDescription key2 = new FsIndexKeyDescription_impl();
-      key2.setFeatureName("Start");
-      key2.setComparator(0);
-      FsIndexKeyDescription key3 = new FsIndexKeyDescription_impl();
-      key3.setTypePriority(true);
-      index.setKeys(new FsIndexKeyDescription[] { key1, key2, key3 });
-
-      FsIndexDescription index2 = new FsIndexDescription_impl();
-      index2.setLabel("testIndex2");
-      index2.setTypeName("Fake");
-      index2.setKind(FsIndexDescription.KIND_SET);
-      FsIndexKeyDescription key1a = new FsIndexKeyDescription_impl();
-      key1a.setFeatureName("TestFeature");
-      key1a.setComparator(1);
-      index2.setKeys(new FsIndexKeyDescription[] { key1a });
-
-      // create primitive AE description
-      primitiveDesc = new AnalysisEngineDescription_impl();
-      primitiveDesc.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
-      primitiveDesc.setPrimitive(true);
-      primitiveDesc.setAnnotatorImplementationName("org.apache.uima.analysis_engine.impl.TestAnnotator");
-      AnalysisEngineMetaData md = primitiveDesc.getAnalysisEngineMetaData();
-      md.setName("Test TAE");
-      md.setDescription("Does not do anything useful.");
-      md.setVersion("1.0");
-      md.setTypeSystem(typeSystem);
-      md.setTypePriorities(typePriorities);
-      md.setFsIndexes(new FsIndexDescription[] { index, index2 });
-      Capability cap1 = new Capability_impl();
-      cap1.setDescription("First fake capability");
-      cap1.addOutputType("Fake", false);
-      cap1.addOutputFeature("Fake:TestFeature");
-      Capability cap2 = new Capability_impl();
-      cap2.setDescription("Second fake capability");
-      cap2.addInputType("Fake", true);
-      cap2.addOutputType("Fake", true);
-      // SimplePrecondition precond1 = new SimplePrecondition_impl();
-      // precond1.setFeatureDescription(feature1);
-      // precond1.setComparisonValue(new String[]{"en,de"});
-      // precond1.setPredicate(SimplePrecondition.LANGUAGE_SUBSUMED);
-      // cap1.setPreconditions(new Precondition[]{precond1});
-      cap1.setLanguagesSupported(new String[] { "en", "de" });
-      cap1.setMimeTypesSupported(new String[] { "text/plain" });
-      md.setCapabilities(new Capability[] { cap1, cap2 });
-      ConfigurationParameter cfgParam1 = new ConfigurationParameter_impl();
-      cfgParam1.setName("param1");
-      cfgParam1.setDescription("Test Parameter 1");
-      cfgParam1.setType("String");
-      ConfigurationParameter cfgParam2 = new ConfigurationParameter_impl();
-      cfgParam2.setName("param2");
-      cfgParam2.setDescription("Test Parameter 2");
-      cfgParam2.setType("Integer");
-      ConfigurationGroup cfgGrp1 = new ConfigurationGroup_impl();
-      cfgGrp1.setNames(new String[] { "cfgGrp1" });
-      cfgGrp1.setConfigurationParameters(new ConfigurationParameter[] { cfgParam1, cfgParam2 });
-      ConfigurationParameter cfgParam3 = new ConfigurationParameter_impl();
-      cfgParam3.setName("param3");
-      cfgParam3.setDescription("Test Parameter 3");
-      cfgParam3.setType("Float");
-      ConfigurationGroup cfgGrp2 = new ConfigurationGroup_impl();
-      cfgGrp2.setNames(new String[] { "cfgGrp2a", "cfgGrp2b" });
-      cfgGrp2.setConfigurationParameters(new ConfigurationParameter[] { cfgParam3 });
-      md.getConfigurationParameterDeclarations().setConfigurationGroups(
-              new ConfigurationGroup[] { cfgGrp1, cfgGrp2 });
-
-      NameValuePair nvp1 = new NameValuePair_impl("param1", "test");
-      NameValuePair nvp2 = new NameValuePair_impl("param2", Integer.valueOf("42"));
-      NameValuePair nvp3a = new NameValuePair_impl("param3", Float.valueOf("2.718281828459045"));
-      NameValuePair nvp3b = new NameValuePair_impl("param3", Float.valueOf("3.1415927"));
-      ConfigurationParameterSettings settings = md.getConfigurationParameterSettings();
-      settings.getSettingsForGroups().put("cfgGrp1", new NameValuePair[] { nvp1, nvp2 });
-      settings.getSettingsForGroups().put("cfgGrp2a", new NameValuePair[] { nvp3a });
-      settings.getSettingsForGroups().put("cfgGrp2b", new NameValuePair[] { nvp3b });
-
-      // create aggregate AE description
-      aggregateDesc = new AnalysisEngineDescription_impl();
-      aggregateDesc.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
-      aggregateDesc.setPrimitive(false);
-      Map<String, MetaDataObject> delegateTaeMap = aggregateDesc.getDelegateAnalysisEngineSpecifiersWithImports();
-      delegateTaeMap.put("Test", primitiveDesc);
-      AnalysisEngineDescription_impl primDesc2 = new AnalysisEngineDescription_impl();
-      primDesc2.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
-      primDesc2.setPrimitive(true);
-      primDesc2.setAnnotatorImplementationName("org.apache.uima.analysis_engine.impl.TestAnnotator");
-      primDesc2.getAnalysisEngineMetaData().setName("fakeAnnotator");
-      primDesc2.getAnalysisEngineMetaData().setCapabilities(
-              new Capability[] { new Capability_impl() });
-      delegateTaeMap.put("Empty", primDesc2);
-      // Can't use URI specifier if we try to produce resource, because it maps to either a SOAP or VINCI adapter,
-      //   and that adapter is not on the class path for this causes a failure in loading
-//      URISpecifier uriSpec = new URISpecifier_impl();
-//      uriSpec.setUri("http://incubator.apache.org/uima");
-//      uriSpec.setProtocol(Constants.PROTOCOL_SOAP);
-      FileResourceSpecifier fileResSpec = new FileResourceSpecifier_impl();
-      fileResSpec.setFileUrl(TEST_DATA_FILE.toURL().toString());
-      FlowControllerDeclaration fcDecl = new FlowControllerDeclaration_impl();
-      fcDecl.setKey("TestFlowController");
-      FlowControllerDescription fcDesc = new FlowControllerDescription_impl();
-      fcDesc.getMetaData().setName("MyTestFlowController");
-      fcDesc.setImplementationName("org.apache.uima.analysis_engine.impl.FlowControllerForErrorTest");
-      fcDecl.setSpecifier(fcDesc);
-      aggregateDesc.setFlowControllerDeclaration(fcDecl);
-
-      ExternalResourceDependency dep = UIMAFramework.getResourceSpecifierFactory()
-              .createExternalResourceDependency();
-      dep.setKey("ResourceKey");
-      dep.setDescription("Test");
-      aggregateDesc.setExternalResourceDependencies(new ExternalResourceDependency[] { dep });
-      ResourceManagerConfiguration resMgrCfg = UIMAFramework.getResourceSpecifierFactory()
-              .createResourceManagerConfiguration();
-      ExternalResourceDescription extRes = UIMAFramework.getResourceSpecifierFactory()
-              .createExternalResourceDescription();
-      extRes.setResourceSpecifier(fileResSpec);
-      extRes.setName("Resource1");
-      extRes.setDescription("Test");
-      resMgrCfg.setExternalResources(new ExternalResourceDescription[] { extRes });
-
-      ExternalResourceBinding binding = UIMAFramework.getResourceSpecifierFactory()
-              .createExternalResourceBinding();
-      binding.setKey("ResourceKey");
-      binding.setResourceName("Resource1");
-      resMgrCfg.setExternalResourceBindings(new ExternalResourceBinding[] {binding});
-      aggregateDesc.setResourceManagerConfiguration(resMgrCfg);
-
-      // AsbCreationSpecifier asbSpec = new AsbCreationSpecifier_impl();
-      // asbSpec.getAsbMetaData().setAsynchronousModeSupported(true);
-      // asbSpec.getAsbMetaData().setSupportedProtocols(new String[]{Constants.PROTOCOL_SOAP});
-      // aggregateDesc.setAsbSpecifier(asbSpec);
-      // AnalysisSequencerCrea1tionSpecifier seqSpec = new
-      // AnalysisSequencerCreationSpecifier_impl();
-      // seqSpec.getAnalysisSequencerMetaData().setSupportedPreconditionTypes(
-      // new String[]{SimplePrecondition.PRECONDITION_TYPE});
-      // aggregateDesc.setSequencerSpecifier(seqSpec);
-      md = aggregateDesc.getAnalysisEngineMetaData();
-      md.setName("Test Aggregate TAE");
-      md.setDescription("Does not do anything useful.");
-      md.setVersion("1.0");
-      // md.setTypeSystem(typeSystem);
-      // md.setFsIndexes(new FsIndexDescription[]{index});
-      md.setCapabilities(primitiveDesc.getAnalysisEngineMetaData().getCapabilities());
-      FixedFlow fixedFlow = new FixedFlow_impl();
-      fixedFlow.setFixedFlow(new String[] { "Test", "Empty" });
-      md.setFlowConstraints(fixedFlow);
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
-    }
+  @Before
+  public void setUp() throws Exception {
+    xmlParser = UIMAFramework.getXMLParser();
+    xmlParser.enableSchemaValidation(true);
+
+    TypeSystemDescription typeSystem = new TypeSystemDescription_impl();
+    TypeDescription type1 = typeSystem.addType("Fake", "<b>Fake</b> Type", "Annotation");
+    type1.addFeature("TestFeature", "For Testing Only", CAS.TYPE_NAME_STRING);
+    TypeDescription enumType = typeSystem.addType("EnumType", "Test Enumerated Type",
+        "uima.cas.String");
+    enumType.setAllowedValues(new AllowedValue[] { new AllowedValue_impl("One", "First Value"),
+        new AllowedValue_impl("Two", "Second Value") });
+
+    TypePriorities typePriorities = new TypePriorities_impl();
+    TypePriorityList priorityList = typePriorities.addPriorityList();
+    priorityList.addType("Fake");
+    priorityList.addType("EnumType");
+
+    FsIndexDescription index = new FsIndexDescription_impl();
+    index.setLabel("testIndex");
+    index.setTypeName("Fake");
+    FsIndexKeyDescription key1 = new FsIndexKeyDescription_impl();
+    key1.setFeatureName("TestFeature");
+    key1.setComparator(1);
+    FsIndexKeyDescription key2 = new FsIndexKeyDescription_impl();
+    key2.setFeatureName("Start");
+    key2.setComparator(0);
+    FsIndexKeyDescription key3 = new FsIndexKeyDescription_impl();
+    key3.setTypePriority(true);
+    index.setKeys(new FsIndexKeyDescription[] { key1, key2, key3 });
+
+    FsIndexDescription index2 = new FsIndexDescription_impl();
+    index2.setLabel("testIndex2");
+    index2.setTypeName("Fake");
+    index2.setKind(FsIndexDescription.KIND_SET);
+    FsIndexKeyDescription key1a = new FsIndexKeyDescription_impl();
+    key1a.setFeatureName("TestFeature");
+    key1a.setComparator(1);
+    index2.setKeys(new FsIndexKeyDescription[] { key1a });
+
+    // create primitive AE description
+    primitiveDesc = new AnalysisEngineDescription_impl();
+    primitiveDesc.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
+    primitiveDesc.setPrimitive(true);
+    primitiveDesc
+        .setAnnotatorImplementationName("org.apache.uima.analysis_engine.impl.TestAnnotator");
+    AnalysisEngineMetaData md = primitiveDesc.getAnalysisEngineMetaData();
+    md.setName("Test TAE");
+    md.setDescription("Does not do anything useful.");
+    md.setVersion("1.0");
+    md.setTypeSystem(typeSystem);
+    md.setTypePriorities(typePriorities);
+    md.setFsIndexes(new FsIndexDescription[] { index, index2 });
+    Capability cap1 = new Capability_impl();
+    cap1.setDescription("First fake capability");
+    cap1.addOutputType("Fake", false);
+    cap1.addOutputFeature("Fake:TestFeature");
+    Capability cap2 = new Capability_impl();
+    cap2.setDescription("Second fake capability");
+    cap2.addInputType("Fake", true);
+    cap2.addOutputType("Fake", true);
+    // SimplePrecondition precond1 = new SimplePrecondition_impl();
+    // precond1.setFeatureDescription(feature1);
+    // precond1.setComparisonValue(new String[]{"en,de"});
+    // precond1.setPredicate(SimplePrecondition.LANGUAGE_SUBSUMED);
+    // cap1.setPreconditions(new Precondition[]{precond1});
+    cap1.setLanguagesSupported(new String[] { "en", "de" });
+    cap1.setMimeTypesSupported(new String[] { "text/plain" });
+    md.setCapabilities(new Capability[] { cap1, cap2 });
+    ConfigurationParameter cfgParam1 = new ConfigurationParameter_impl();
+    cfgParam1.setName("param1");
+    cfgParam1.setDescription("Test Parameter 1");
+    cfgParam1.setType("String");
+    ConfigurationParameter cfgParam2 = new ConfigurationParameter_impl();
+    cfgParam2.setName("param2");
+    cfgParam2.setDescription("Test Parameter 2");
+    cfgParam2.setType("Integer");
+    ConfigurationGroup cfgGrp1 = new ConfigurationGroup_impl();
+    cfgGrp1.setNames(new String[] { "cfgGrp1" });
+    cfgGrp1.setConfigurationParameters(new ConfigurationParameter[] { cfgParam1, cfgParam2 });
+    ConfigurationParameter cfgParam3 = new ConfigurationParameter_impl();
+    cfgParam3.setName("param3");
+    cfgParam3.setDescription("Test Parameter 3");
+    cfgParam3.setType("Float");
+    ConfigurationGroup cfgGrp2 = new ConfigurationGroup_impl();
+    cfgGrp2.setNames(new String[] { "cfgGrp2a", "cfgGrp2b" });
+    cfgGrp2.setConfigurationParameters(new ConfigurationParameter[] { cfgParam3 });
+    md.getConfigurationParameterDeclarations()
+        .setConfigurationGroups(new ConfigurationGroup[] { cfgGrp1, cfgGrp2 });
+
+    NameValuePair nvp1 = new NameValuePair_impl("param1", "test");
+    NameValuePair nvp2 = new NameValuePair_impl("param2", Integer.valueOf("42"));
+    NameValuePair nvp3a = new NameValuePair_impl("param3", Float.valueOf("2.718281828459045"));
+    NameValuePair nvp3b = new NameValuePair_impl("param3", Float.valueOf("3.1415927"));
+    ConfigurationParameterSettings settings = md.getConfigurationParameterSettings();
+    settings.getSettingsForGroups().put("cfgGrp1", new NameValuePair[] { nvp1, nvp2 });
+    settings.getSettingsForGroups().put("cfgGrp2a", new NameValuePair[] { nvp3a });
+    settings.getSettingsForGroups().put("cfgGrp2b", new NameValuePair[] { nvp3b });
+
+    // create aggregate AE description
+    aggregateDesc = new AnalysisEngineDescription_impl();
+    aggregateDesc.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
+    aggregateDesc.setPrimitive(false);
+    Map<String, MetaDataObject> delegateTaeMap = aggregateDesc
+        .getDelegateAnalysisEngineSpecifiersWithImports();
+    delegateTaeMap.put("Test", primitiveDesc);
+    AnalysisEngineDescription_impl primDesc2 = new AnalysisEngineDescription_impl();
+    primDesc2.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
+    primDesc2.setPrimitive(true);
+    primDesc2.setAnnotatorImplementationName("org.apache.uima.analysis_engine.impl.TestAnnotator");
+    primDesc2.getAnalysisEngineMetaData().setName("fakeAnnotator");
+    primDesc2.getAnalysisEngineMetaData()
+        .setCapabilities(new Capability[] { new Capability_impl() });
+    delegateTaeMap.put("Empty", primDesc2);
+    // Can't use URI specifier if we try to produce resource, because it maps to either a SOAP or
+    // VINCI adapter,
+    // and that adapter is not on the class path for this causes a failure in loading
+    // URISpecifier uriSpec = new URISpecifier_impl();
+    // uriSpec.setUri("http://incubator.apache.org/uima");
+    // uriSpec.setProtocol(Constants.PROTOCOL_SOAP);
+    FileResourceSpecifier fileResSpec = new FileResourceSpecifier_impl();
+    fileResSpec.setFileUrl(TEST_DATA_FILE.toURL().toString());
+    FlowControllerDeclaration fcDecl = new FlowControllerDeclaration_impl();
+    fcDecl.setKey("TestFlowController");
+    FlowControllerDescription fcDesc = new FlowControllerDescription_impl();
+    fcDesc.getMetaData().setName("MyTestFlowController");
+    fcDesc.setImplementationName("org.apache.uima.analysis_engine.impl.FlowControllerForErrorTest");
+    fcDecl.setSpecifier(fcDesc);
+    aggregateDesc.setFlowControllerDeclaration(fcDecl);
+
+    ExternalResourceDependency dep = UIMAFramework.getResourceSpecifierFactory()
+        .createExternalResourceDependency();
+    dep.setKey("ResourceKey");
+    dep.setDescription("Test");
+    aggregateDesc.setExternalResourceDependencies(new ExternalResourceDependency[] { dep });
+    ResourceManagerConfiguration resMgrCfg = UIMAFramework.getResourceSpecifierFactory()
+        .createResourceManagerConfiguration();
+    ExternalResourceDescription extRes = UIMAFramework.getResourceSpecifierFactory()
+        .createExternalResourceDescription();
+    extRes.setResourceSpecifier(fileResSpec);
+    extRes.setName("Resource1");
+    extRes.setDescription("Test");
+    resMgrCfg.setExternalResources(new ExternalResourceDescription[] { extRes });
+
+    ExternalResourceBinding binding = UIMAFramework.getResourceSpecifierFactory()
+        .createExternalResourceBinding();
+    binding.setKey("ResourceKey");
+    binding.setResourceName("Resource1");
+    resMgrCfg.setExternalResourceBindings(new ExternalResourceBinding[] { binding });
+    aggregateDesc.setResourceManagerConfiguration(resMgrCfg);
+
+    // AsbCreationSpecifier asbSpec = new AsbCreationSpecifier_impl();
+    // asbSpec.getAsbMetaData().setAsynchronousModeSupported(true);
+    // asbSpec.getAsbMetaData().setSupportedProtocols(new String[]{Constants.PROTOCOL_SOAP});
+    // aggregateDesc.setAsbSpecifier(asbSpec);
+    // AnalysisSequencerCrea1tionSpecifier seqSpec = new
+    // AnalysisSequencerCreationSpecifier_impl();
+    // seqSpec.getAnalysisSequencerMetaData().setSupportedPreconditionTypes(
+    // new String[]{SimplePrecondition.PRECONDITION_TYPE});
+    // aggregateDesc.setSequencerSpecifier(seqSpec);
+    md = aggregateDesc.getAnalysisEngineMetaData();
+    md.setName("Test Aggregate TAE");
+    md.setDescription("Does not do anything useful.");
+    md.setVersion("1.0");
+    // md.setTypeSystem(typeSystem);
+    // md.setFsIndexes(new FsIndexDescription[]{index});
+    md.setCapabilities(primitiveDesc.getAnalysisEngineMetaData().getCapabilities());
+    FixedFlow fixedFlow = new FixedFlow_impl();
+    fixedFlow.setFixedFlow(new String[] { "Test", "Empty" });
+    md.setFlowConstraints(fixedFlow);
   }
 
-  @Override
-  public void tearDown() {
+  @After
+  public void tearDown() throws Exception {
+    // Note that the XML parser is a singleton in the framework, so we have to set this back to the
+    // default.
+    xmlParser.enableSchemaValidation(false);
     primitiveDesc = null;
     aggregateDesc = null;
   }
-  
+
+  @Test
   public void testMulticoreInitialize() throws Exception {
     ResourceManager resourceManager = UIMAFramework.newDefaultResourceManager();
     ConfigurationManager configManager = UIMAFramework.newConfigurationManager();
     Logger logger = UIMAFramework.getLogger(this.getClass());
     logger.setResourceManager(resourceManager);
- 
+
     UimaContext uimaContext = UIMAFramework.newUimaContext(logger, resourceManager, configManager);
-    
+
     final Map<String, Object> p = new HashMap<String, Object>();
-    p.put(UIMAFramework.CAS_INITIAL_HEAP_SIZE,  200);
+    p.put(UIMAFramework.CAS_INITIAL_HEAP_SIZE, 200);
     p.put(Resource.PARAM_CONFIG_MANAGER, configManager);
-    p.put(Resource.PARAM_RESOURCE_MANAGER,  UIMAFramework.newDefaultResourceManager());
+    p.put(Resource.PARAM_RESOURCE_MANAGER, UIMAFramework.newDefaultResourceManager());
     p.put(Resource.PARAM_UIMA_CONTEXT, uimaContext);
-    int numberOfThreads = Math.min(50, Utilities.numberOfCores * 5); 
+    int numberOfThreads = Math.min(50, Utilities.numberOfCores * 5);
     final AnalysisEngine[] aes = new AnalysisEngine[numberOfThreads];
-    System.out.format("test multicore initialize with %d threads%n",
-        numberOfThreads);
-    
-    
+    System.out.format("test multicore initialize with %d threads%n", numberOfThreads);
+
     MultiThreadUtils.Run2isb run2isb = new MultiThreadUtils.Run2isb() {
-      
       public void call(int i, int r, StringBuilder sb) throws Exception {
         Random random = new Random();
         for (int j = 0; j < 2; j++) {
-          aes[i] = UIMAFramework.produceAnalysisEngine(primitiveDesc, p);     
-  //        System.out.println(sb.toString());
-  //        System.out.print('.');
+          aes[i] = UIMAFramework.produceAnalysisEngine(primitiveDesc, p);
+          // System.out.println(sb.toString());
+          // System.out.print('.');
           if ((i % 2) == 0) {
             Thread.sleep(0, random.nextInt(2000));
           }
         }
       }
-    };  
-    MultiThreadUtils.tstMultiThread("MultiCoreInitialize",  numberOfThreads,  100, run2isb, MultiThreadUtils.emptyReset);
-    assertTrue(!aes[0].equals(aes[1]));
-    
+    };
+    MultiThreadUtils.tstMultiThread("MultiCoreInitialize", numberOfThreads, 100, run2isb,
+        MultiThreadUtils.emptyReset);
+    assertThat(aes[0]).isNotEqualTo(aes[1]);
+
     run2isb = new MultiThreadUtils.Run2isb() {
-      
       public void call(int i, int r, StringBuilder sb) throws Exception {
         Random random = new Random();
         for (int j = 0; j < 2; j++) {
-          aes[i] = UIMAFramework.produceAnalysisEngine(aggregateDesc, p);     
-  //        System.out.println(sb.toString());
-  //        System.out.print('.');
+          aes[i] = UIMAFramework.produceAnalysisEngine(aggregateDesc, p);
+          // System.out.println(sb.toString());
+          // System.out.print('.');
           if ((i % 2) == 0) {
             Thread.sleep(0, random.nextInt(5000));
           }
         }
       }
     };
-    MultiThreadUtils.tstMultiThread("MultiCoreInitialize",  numberOfThreads,  100, run2isb, MultiThreadUtils.emptyReset);
-    assertTrue(!aes[0].equals(aes[1]));
 
-    
-//    System.out.println("");
+    MultiThreadUtils.tstMultiThread("MultiCoreInitialize", numberOfThreads, 100, run2isb,
+        MultiThreadUtils.emptyReset);
+
+    assertThat(aes[0]).isNotEqualTo(aes[1]);
   }
-  
-  
-  
-  public void testXMLization() throws Exception {
-    try {
-      // write objects to XML
-
-      StringWriter writer = new StringWriter();
-      primitiveDesc.toXML(writer);
-      String primitiveDescXml = writer.getBuffer().toString();
-      // System.out.println(primitiveDescXml);
-      writer = new StringWriter();
-      aggregateDesc.toXML(writer);
-      String aggregateDescXml = writer.getBuffer().toString();
-      // System.out.println(aggregateDescXml);
-
-      // parse objects from XML
-      InputStream is = new ByteArrayInputStream(primitiveDescXml.getBytes(encoding));
-      AnalysisEngineDescription newPrimitiveDesc = (AnalysisEngineDescription) UIMAFramework
-              .getXMLParser().parse(new XMLInputSource(is, null));
-      is = new ByteArrayInputStream(aggregateDescXml.getBytes(encoding));
-      AnalysisEngineDescription newAggregateDesc = (AnalysisEngineDescription) UIMAFramework
-              .getXMLParser().parse(new XMLInputSource(is, null));
-
-      Assert.assertEquals(primitiveDesc, newPrimitiveDesc);
-      Assert.assertEquals(aggregateDesc, newAggregateDesc);
-
-      // test a complex descriptor
-      XMLInputSource in = new XMLInputSource(JUnitExtension
-              .getFile("AnnotatorContextTest/AnnotatorWithGroupsAndNonGroupParams.xml"));
-      AnalysisEngineDescription desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-      OperationalProperties opProps = desc.getAnalysisEngineMetaData().getOperationalProperties();
-      assertNotNull(opProps);
-      assertEquals(true, opProps.getModifiesCas());
-      assertEquals(true, opProps.isMultipleDeploymentAllowed());
-      writer = new StringWriter();
-      desc.toXML(writer);
-      String descXml = writer.getBuffer().toString();
-      is = new ByteArrayInputStream(descXml.getBytes(encoding));
-      AnalysisEngineDescription newDesc = (AnalysisEngineDescription) UIMAFramework.getXMLParser()
-              .parse(new XMLInputSource(is, null));
-      Assert.assertEquals(desc, newDesc);
-
-      // test a descriptor that includes a CasConsumer
-      in = new XMLInputSource(JUnitExtension
-              .getFile("TextAnalysisEngineImplTest/AggregateTaeWithCasConsumer.xml"));
-      desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-      writer = new StringWriter();
-      desc.toXML(writer);
-      descXml = writer.getBuffer().toString();
-      is = new ByteArrayInputStream(descXml.getBytes(encoding));
-      newDesc = (AnalysisEngineDescription) UIMAFramework.getXMLParser().parse(
-              new XMLInputSource(is, null));
-      Assert.assertEquals(desc, newDesc);
-
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
+
+  @Test
+  public void thatComplexDescriptorCanBeXMLized() throws Exception {
+    // test a complex descriptor
+    AnalysisEngineDescription desc = xmlParser.parseAnalysisEngineDescription(new XMLInputSource(
+        getFile("AnnotatorContextTest/AnnotatorWithGroupsAndNonGroupParams.xml")));
+    OperationalProperties opProps = desc.getAnalysisEngineMetaData().getOperationalProperties();
+
+    assertThat(opProps).isNotNull();
+    assertThat(opProps.getModifiesCas()).isTrue();
+    assertThat(opProps.isMultipleDeploymentAllowed()).isTrue();
+
+    try (InputStream is = new ByteArrayInputStream(toXmlString(desc).getBytes(encoding))) {
+      AnalysisEngineDescription newDesc = xmlParser
+          .parseAnalysisEngineDescription(new XMLInputSource(is, null));
+      assertThat(newDesc).isEqualTo(desc);
+    }
+  }
+
+  @Test
+  public void thatDescriptorWithCasConsumerCanBeXMLized() throws Exception {
+    // test a descriptor that includes a CasConsumer
+    AnalysisEngineDescription desc = xmlParser.parseAnalysisEngineDescription(
+        new XMLInputSource(getFile("TextAnalysisEngineImplTest/AggregateTaeWithCasConsumer.xml")));
+    try (InputStream is = new ByteArrayInputStream(toXmlString(desc).getBytes(encoding))) {
+      AnalysisEngineDescription newDesc = xmlParser
+          .parseAnalysisEngineDescription(new XMLInputSource(is, null));
+      assertThat(newDesc).isEqualTo(desc);
+    }
+  }
+
+  @Test
+  public void thatPrimitiveDescriptorCanBeXMLized() throws Exception {
+    // write objects to XML
+    String primitiveDescXml = toXmlString(primitiveDesc);
+
+    // parse objects from XML
+    try (InputStream is = new ByteArrayInputStream(primitiveDescXml.getBytes(encoding))) {
+      AnalysisEngineDescription newPrimitiveDesc = xmlParser
+          .parseAnalysisEngineDescription(new XMLInputSource(is, null));
+      assertThat(newPrimitiveDesc).isEqualTo(primitiveDesc);
+    }
+  }
+
+  @Test
+  public void thatAggregateDescriptorCanBeXMLized() throws Exception {
+    String aggregateDescXml = toXmlString(aggregateDesc);
+    try (InputStream is = new ByteArrayInputStream(aggregateDescXml.getBytes(encoding))) {
+      AnalysisEngineDescription newAggregateDesc = xmlParser
+          .parseAnalysisEngineDescription(new XMLInputSource(is, null));
+      assertThat(newAggregateDesc).isEqualTo(aggregateDesc);
     }
   }
- 
+
+  @Test
   public void testDefaultingOperationalParameters() throws Exception {
     XMLInputSource in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/TestPrimitiveOperationalParmsDefaults.xml"));
-    AnalysisEngineDescription desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
+        .getFile("TextAnalysisEngineImplTest/TestPrimitiveOperationalParmsDefaults.xml"));
+    AnalysisEngineDescription desc = xmlParser.parseAnalysisEngineDescription(in);
     OperationalProperties opProps = desc.getAnalysisEngineMetaData().getOperationalProperties();
-    assertNotNull(opProps);
-    assertEquals(true, opProps.getModifiesCas());
-    assertEquals(false, opProps.isMultipleDeploymentAllowed());
-  }
-
-  public void testSerialization() throws Exception {
-    try {
-      // serialize objects to byte array
 
-      byte[] primitiveDescBytes = SerializationUtils.serialize(primitiveDesc);
-      byte[] aggregateDescBytes = SerializationUtils.serialize(aggregateDesc);
+    assertThat(opProps).isNotNull();
+    assertThat(opProps.getModifiesCas()).isTrue();
+    assertThat(opProps.isMultipleDeploymentAllowed()).isFalse();
+  }
 
-      // deserialize
-      AnalysisEngineDescription newPrimitiveDesc = (AnalysisEngineDescription) SerializationUtils
-              .deserialize(primitiveDescBytes);
-      AnalysisEngineDescription newAggregateDesc = (AnalysisEngineDescription) SerializationUtils
-              .deserialize(aggregateDescBytes);
+  @Test
+  public void thatPrimitiveDescriptionCanBeSerialized() throws Exception {
+    byte[] primitiveDescBytes = SerializationUtils.serialize(primitiveDesc);
+    AnalysisEngineDescription newPrimitiveDesc = (AnalysisEngineDescription) SerializationUtils
+        .deserialize(primitiveDescBytes);
+    assertThat(newPrimitiveDesc).isEqualTo(primitiveDesc);
+  }
 
-      Assert.assertEquals(primitiveDesc, newPrimitiveDesc);
-      Assert.assertEquals(aggregateDesc, newAggregateDesc);
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
-    }
+  @Test
+  public void thatAggregateDescriptionCanBeSerialized() throws Exception {
+    byte[] aggregateDescBytes = SerializationUtils.serialize(aggregateDesc);
+    AnalysisEngineDescription newAggregateDesc = (AnalysisEngineDescription) SerializationUtils
+        .deserialize(aggregateDescBytes);
+    assertThat(newAggregateDesc).isEqualTo(aggregateDesc);
   }
 
+  @Test
   public void testDelegateImports() throws Exception {
     // create aggregate TAE description and add delegate AE import
     AnalysisEngineDescription testAgg = new AnalysisEngineDescription_impl();
-    Map<String, MetaDataObject> delegateMap = testAgg.getDelegateAnalysisEngineSpecifiersWithImports();
+    Map<String, MetaDataObject> delegateMap = testAgg
+        .getDelegateAnalysisEngineSpecifiersWithImports();
     Import_impl delegateImport = new Import_impl();
-    delegateImport.setLocation(JUnitExtension.getFile(
-            "TextAnalysisEngineImplTest/TestPrimitiveTae1.xml").toURI().toURL().toString());
+    delegateImport.setLocation(
+        getFile("TextAnalysisEngineImplTest/TestPrimitiveTae1.xml").toURI().toURL().toString());
     delegateMap.put("key", delegateImport);
 
-    // test that import is resolved
-    Map<String, ResourceSpecifier> mapWithImportsResolved = testAgg.getDelegateAnalysisEngineSpecifiers();
-    assertEquals(1, mapWithImportsResolved.size());
-    ResourceSpecifier obj = mapWithImportsResolved.values().iterator().next();
-    assertTrue(obj instanceof AnalysisEngineDescription);
+    assertThat(testAgg.getDelegateAnalysisEngineSpecifiers().values()) //
+        .as("test that import is resolved") //
+        .hasSize(1) //
+        .allMatch(d -> d instanceof AnalysisEngineDescription);
 
-    // test that remove works
     delegateMap.remove("key");
-    mapWithImportsResolved = testAgg.getDelegateAnalysisEngineSpecifiers();
-    assertEquals(0, mapWithImportsResolved.size());
+    assertThat(testAgg.getDelegateAnalysisEngineSpecifiers()) //
+        .as("test that remove works") //
+        .isEmpty();
 
-    // test the re-add works
     delegateMap.put("key", delegateImport);
-    mapWithImportsResolved = testAgg.getDelegateAnalysisEngineSpecifiers();
-    assertEquals(1, mapWithImportsResolved.size());
-    obj = mapWithImportsResolved.values().iterator().next();
-    assertTrue(obj instanceof AnalysisEngineDescription);
+    assertThat(testAgg.getDelegateAnalysisEngineSpecifiers().values()) //
+        .as("test the re-add works") //
+        .hasSize(1) //
+        .allMatch(d -> d instanceof AnalysisEngineDescription);
 
     // serialize to XML, preserving imports
     testAgg.toXML(new StringWriter(), true);
-
-    // verify that imports are still resolved
-    mapWithImportsResolved = testAgg.getDelegateAnalysisEngineSpecifiers();
-    assertEquals(1, mapWithImportsResolved.size());
-    obj = mapWithImportsResolved.values().iterator().next();
-    assertTrue(obj instanceof AnalysisEngineDescription);
+    assertThat(testAgg.getDelegateAnalysisEngineSpecifiers().values()) //
+        .as("verify that imports are still resolved") //
+        .hasSize(1) //
+        .allMatch(d -> d instanceof AnalysisEngineDescription);
   }
 
+  @Test
   public void testDoFullValidation() throws Exception {
     // try some descriptors that are invalid due to config. param problems
     for (int i = 1; i <= 13; i++) {
-      _testInvalidDescriptor(JUnitExtension
-              .getFile("TextAnalysisEngineImplTest/InvalidConfigParams" + i + ".xml"));
+      assertDescriptorIsNotValid("TextAnalysisEngineImplTest/InvalidConfigParams" + i + ".xml");
     }
+
     // try a descriptor that's invalid due to an unsatisfied resource dependency
-    _testInvalidDescriptor(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/UnsatisfiedResourceDependency.xml"));
+    assertDescriptorIsNotValid("TextAnalysisEngineImplTest/UnsatisfiedResourceDependency.xml");
+
     // try some invalid operational properties
-    _testInvalidDescriptor(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/InvalidAggregateSegmenter.xml"));
+    assertDescriptorIsNotValid("TextAnalysisEngineImplTest/InvalidAggregateSegmenter.xml");
+
     // invalid fs indexes
-    _testInvalidDescriptor(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/InvalidFsIndexes.xml"));
+    assertDescriptorIsNotValid("TextAnalysisEngineImplTest/InvalidFsIndexes.xml");
+
     // circular import
-    _testInvalidDescriptor(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/AggregateThatImportsItself.xml"));
+    assertDescriptorIsNotValid("TextAnalysisEngineImplTest/AggregateThatImportsItself.xml");
 
     // try some that should work
-    XMLInputSource in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/AggregateTaeWithConfigParamOverrides.xml"));
-    AnalysisEngineDescription desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();
-    in = new XMLInputSource(JUnitExtension
-            .getFile("AnnotatorContextTest/AnnotatorWithGroupsAndNonGroupParams.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();
+    assertDescriptorIsValid("TextAnalysisEngineImplTest/AggregateTaeWithConfigParamOverrides.xml");
+
+    assertDescriptorIsValid("AnnotatorContextTest/AnnotatorWithGroupsAndNonGroupParams.xml");
 
     // try aggregate containing remote service - should work even if can't connect
-    in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/AggregateWithUnknownRemoteComponent.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();
+    assertDescriptorIsValid("TextAnalysisEngineImplTest/AggregateWithUnknownRemoteComponent.xml");
 
     // try aggregate with sofas
-    in = new XMLInputSource(JUnitExtension.getFile("CpeSofaTest/TransAnnotatorAggregate.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();
+    assertDescriptorIsValid("CpeSofaTest/TransAnnotatorAggregate.xml");
 
     // try another aggregate with sofas
-    in = new XMLInputSource(JUnitExtension
-            .getFile("CpeSofaTest/TransAnnotatorAndTestAnnotatorAggregate.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();
+    assertDescriptorIsValid("CpeSofaTest/TransAnnotatorAndTestAnnotatorAggregate.xml");
 
     // try primitive with duplicate configuration group definitions
-    in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/AnnotatorWithDuplicateConfigurationGroups.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();
+    assertDescriptorIsValid(
+        "TextAnalysisEngineImplTest/AnnotatorWithDuplicateConfigurationGroups.xml");
 
     // try aggregate with duplicate configuration group definitions
-    in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/AggregateWithDuplicateGroupOverrides.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();
-    
-    //test aggregate with import by name and configuration parameter overrides
-    in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/AeWithConfigParamOverridesAndImportByName.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    ResourceManager resMgr = UIMAFramework.newDefaultResourceManager();
-    File dataPathDir = JUnitExtension.getFile("TextAnalysisEngineImplTest/dataPathDir");
+    assertDescriptorIsValid("TextAnalysisEngineImplTest/AggregateWithDuplicateGroupOverrides.xml");
+
+    // test UIMA C++ descriptor (should succeed even though annotator library doesn't exist)
+    assertDescriptorIsValid("TextAnalysisEngineImplTest/TestUimaCppAe.xml");
+
+    assertDescriptorIsValid("TextAnalysisEngineImplTest/TestAggregateContainingCppAnnotator.xml");
+  }
+
+  @Test
+  public void thatAggregateWithImportByNameAndConfigParameterOverridesValidates() throws Exception {
+    // test aggregate with import by name and configuration parameter overrides
+    XMLInputSource in = new XMLInputSource(
+        getFile("TextAnalysisEngineImplTest/AeWithConfigParamOverridesAndImportByName.xml"));
+    AnalysisEngineDescription desc = xmlParser.parseAnalysisEngineDescription(in);
+    ResourceManager resMgr = newDefaultResourceManager();
+    File dataPathDir = getFile("TextAnalysisEngineImplTest/dataPathDir");
     resMgr.setDataPath(dataPathDir.getCanonicalPath());
     desc.doFullValidation(resMgr);
-    
-    //test UIMA C++ descriptor (should succeed even though annotator library doesn't exist)
-    in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/TestUimaCppAe.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();
-    
-    in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/TestAggregateContainingCppAnnotator.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    desc.doFullValidation();    
   }
-  
+
+  @Test
   public void testValidate() throws Exception {
-    //test aggregate with import by name and configuration parameter overrides
-    XMLInputSource in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/AeWithConfigParamOverridesAndImportByName.xml"));
-    AnalysisEngineDescription desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    ResourceManager resMgr = UIMAFramework.newDefaultResourceManager();
-    File dataPathDir = JUnitExtension.getFile("TextAnalysisEngineImplTest/dataPathDir");
+    // test aggregate with import by name and configuration parameter overrides
+    XMLInputSource in = new XMLInputSource(
+        getFile("TextAnalysisEngineImplTest/AeWithConfigParamOverridesAndImportByName.xml"));
+    AnalysisEngineDescription desc = xmlParser.parseAnalysisEngineDescription(in);
+    ResourceManager resMgr = newDefaultResourceManager();
+    File dataPathDir = getFile("TextAnalysisEngineImplTest/dataPathDir");
     resMgr.setDataPath(dataPathDir.getCanonicalPath());
-    desc.validate(resMgr); 
-    
-    //test invalid aggregate with undefined key in flow
-    in = new XMLInputSource(JUnitExtension
-            .getFile("TextAnalysisEngineImplTest/InvalidAggregate_UndefinedKeyInFlow.xml"));
-    desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-    try {
-      desc.validate();  
-      fail();
-    }
-    catch(ResourceInitializationException e) {
-      //e.printStackTrace();
-      assertEquals(ResourceInitializationException.UNDEFINED_KEY_IN_FLOW, e.getMessageKey());
-      assertNotNull(e.getMessage());
-      assertFalse(e.getMessage().startsWith("EXCEPTION MESSAGE LOCALIZATION FAILED"));
-    }
+    desc.validate(resMgr);
+
+    // test invalid aggregate with undefined key in flow
+    in = new XMLInputSource(
+        getFile("TextAnalysisEngineImplTest/InvalidAggregate_UndefinedKeyInFlow.xml"));
+    AnalysisEngineDescription desc2 = xmlParser.parseAnalysisEngineDescription(in);
+
+    assertThatThrownBy(() -> desc2.validate()) //
+        .isInstanceOf(ResourceInitializationException.class) //
+        .extracting("messageKey", "message") //
+        .satisfies(t -> { //
+          assertThat(t.get(0)).isEqualTo(UNDEFINED_KEY_IN_FLOW); //
+          assertThat((String) t.get(1)).doesNotStartWith("EXCEPTION MESSAGE LOCALIZATION FAILED");
+        });
   }
 
+  @Test
   public void testGetAllComponentSpecifiers() throws Exception {
-    try {
-      Map<String, ResourceSpecifier> allSpecs = aggregateDesc.getAllComponentSpecifiers(null);
-      FlowControllerDescription fcDesc = (FlowControllerDescription) allSpecs
-              .get("TestFlowController");
-      assertNotNull(fcDesc);
-      assertEquals("MyTestFlowController", fcDesc.getMetaData().getName());
-      AnalysisEngineDescription aeDesc = (AnalysisEngineDescription) allSpecs.get("Test");
-      assertNotNull(aeDesc);
-      assertEquals("Test TAE", aeDesc.getMetaData().getName());
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
-    }
+    Map<String, ResourceSpecifier> allSpecs = aggregateDesc.getAllComponentSpecifiers(null);
 
-  }
-  
-  public void testDocumentAnnotationRedefine() {
-    final String tsDescriptor = 
-      "org/apache/uima/analysis_engine/impl/documentAnnotationRedefinitionTS.xml";
-    File file = JUnitExtension.getFile(tsDescriptor);
-    XMLParser parser = UIMAFramework.getXMLParser();
-    boolean resourceInitExc = false;
-    try {
-      TypeSystemDescription tsd = (TypeSystemDescription) parser.parse(new XMLInputSource(file));
-      CasCreationUtils.createCas(tsd, null, new FsIndexDescription[0]);
-    } catch (InvalidXMLException e) {
-      e.printStackTrace();
-      assertTrue(false);
-    } catch (IOException e) {
-      e.printStackTrace();
-      assertTrue(false);
-    } catch (ResourceInitializationException e) {
-      resourceInitExc = true;
-    }
-    assertTrue(resourceInitExc);
+    assertThat((FlowControllerDescription) allSpecs.get("TestFlowController")) //
+        .isNotNull() //
+        .extracting(desc -> desc.getMetaData().getName()).isEqualTo("MyTestFlowController");
+
+    assertThat((AnalysisEngineDescription) allSpecs.get("Test")) //
+        .isNotNull() //
+        .extracting(desc -> desc.getMetaData().getName()).isEqualTo("Test TAE");
   }
 
-  protected void _testInvalidDescriptor(File aFile) throws IOException {
-    assertTrue(aFile.exists());
-    XMLInputSource in = new XMLInputSource(aFile);
-    Exception ex = null;
-    try {
-      AnalysisEngineDescription desc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(in);
-      desc.doFullValidation();
-    } catch (InvalidXMLException e) {
-      // e.printStackTrace();
-      ex = e;
-    } catch (ResourceInitializationException e) {
-      // e.printStackTrace();
-      ex = e;
-    }
-    Assert.assertNotNull(ex);
-    Assert.assertNotNull(ex.getMessage());
-    Assert.assertFalse(ex.getMessage().startsWith("EXCEPTION MESSAGE LOCALIZATION FAILED"));
+  @Test
+  public void testDocumentAnnotationRedefine() throws Exception {
+    File file = getFile(
+        "org/apache/uima/analysis_engine/impl/documentAnnotationRedefinitionTS.xml");
+    TypeSystemDescription tsd = xmlParser.parseTypeSystemDescription(new XMLInputSource(file));
+
+    assertThatThrownBy(() -> createCas(tsd, null, new FsIndexDescription[0]))
+        .isInstanceOf(ResourceInitializationException.class);
   }
 
+  @Test
   public void testNoDelegatesToResolve() throws Exception {
     ResourceSpecifierFactory f = UIMAFramework.getResourceSpecifierFactory();
+    
     AnalysisEngineDescription outer = f.createAnalysisEngineDescription();
     AnalysisEngineDescription inner = f.createAnalysisEngineDescription();
     outer.getDelegateAnalysisEngineSpecifiersWithImports().put("inner", inner);
 
-    StringWriter outerXml = new StringWriter();
-    outer.toXML(outerXml);
-    
+    String outerXml = toXmlString(outer);
+
     // Resolving the imports removes the inner AE description
     outer.resolveImports(UIMAFramework.newDefaultResourceManager());
-    
-    StringWriter outerXml2 = new StringWriter();
-    outer.toXML(outerXml2);
 
-    Assert.assertEquals(outerXml.toString(), outerXml2.toString());
+    String outerXml2 = toXmlString(outer);
+
+    assertThat(outerXml2).isEqualTo(outerXml);
+  }
+
+  private void assertDescriptorIsValid(String aPath)
+      throws IOException, InvalidXMLException, ResourceInitializationException {
+    XMLInputSource in = new XMLInputSource(getFile(aPath));
+    AnalysisEngineDescription desc = xmlParser.parseAnalysisEngineDescription(in);
+    desc.doFullValidation();
+  }
+
+  private void assertDescriptorIsNotValid(String aPath) throws IOException {
+    File file = getFile(aPath);
+
+    assertThat(file).exists();
+
+    assertThatThrownBy(
+        () -> xmlParser.parseAnalysisEngineDescription(new XMLInputSource(file)).doFullValidation())
+            .satisfiesAnyOf( //
+                e -> assertThat(e).isInstanceOf(ResourceInitializationException.class), //
+                e -> assertThat(e).isInstanceOf(InvalidXMLException.class)) //
+            .extracting("message", as(InstanceOfAssertFactories.STRING)) //
+            .doesNotStartWith("EXCEPTION MESSAGE LOCALIZATION FAILED");
+  }
+
+  private String toXmlString(XMLizable aObject) throws IOException, SAXException {
+    StringWriter writer = new StringWriter();
+    aObject.toXML(writer);
+    return writer.getBuffer().toString();
   }
 }
diff --git a/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java b/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java
index 04cc122..745fd24 100644
--- a/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java
+++ b/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java
@@ -16,53 +16,53 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.uima.resource.metadata.impl;
 
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static org.apache.uima.UIMAFramework.getResourceSpecifierFactory;
+import static org.apache.uima.internal.util.SerializationUtils.deserialize;
+import static org.apache.uima.internal.util.SerializationUtils.serialize;
+import static org.assertj.core.api.Assertions.assertThat;
+
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.apache.uima.UIMAFramework;
-import org.apache.uima.internal.util.SerializationUtils;
 import org.apache.uima.resource.metadata.ConfigurationParameterSettings;
 import org.apache.uima.resource.metadata.MetaDataObject;
 import org.apache.uima.resource.metadata.NameValuePair;
-import org.apache.uima.resource.metadata.impl.MetaDataObject_impl.MetaDataAttr;
-import org.apache.uima.test.junit_extension.JUnitExtension;
+import org.apache.uima.test.junit_extension.PrintExceptionsWhenRunFromCommandLineRule;
 import org.apache.uima.util.XMLParser;
+import org.apache.uima.util.XMLizable;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
-
-import org.junit.Assert;
-import junit.framework.TestCase;
+import org.xml.sax.SAXException;
 
 /**
  * Tests the MetaDataObject_impl class.
- * 
  */
-public class MetaDataObject_implTest extends TestCase {
+public class MetaDataObject_implTest {
+  public @Rule TestRule exceptingHandlingRule = new PrintExceptionsWhenRunFromCommandLineRule();
 
-  /**
-   * Constructor for MetaDataObject_implTest.
-   * 
-   * @param arg0
-   */
-  public MetaDataObject_implTest(String arg0) {
-    super(arg0);
-  }
+  private TestFruitObject unknownFruit;
+  private TestFruitObject apple1;
+  private TestFruitObject apple2;
+  private TestFruitObject orange;
+  private TestFruitBagObject fruitBag;
 
-  /**
-   * @see TestCase#setUp()
-   */
-  protected void setUp() throws Exception {
-    super.setUp();
+  @Before
+  public void setUp() {
     // create an object that can represent a fruit
     unknownFruit = new TestFruitObject();
   
@@ -72,7 +72,7 @@ public class MetaDataObject_implTest extends TestCase {
     apple1.setAttributeValue("color", "red");
     apple1.setAttributeValue("avgWeightLbs", 0.3F);
     apple1.setAttributeValue("avgCostCents", 40);
-    apple1.setAttributeValue("citrus", Boolean.FALSE);
+    apple1.setAttributeValue("citrus", FALSE);
     apple1.setAttributeValue("commonUses", new String[] { "baking", "snack" });
 
     apple2 = new TestFruitObject();
@@ -80,7 +80,7 @@ public class MetaDataObject_implTest extends TestCase {
     apple2.setAttributeValue("color", "red");
     apple2.setAttributeValue("avgWeightLbs", 0.3F);
     apple2.setAttributeValue("avgCostCents", 40);
-    apple2.setAttributeValue("citrus", Boolean.FALSE);
+    apple2.setAttributeValue("citrus", FALSE);
     apple2.setAttributeValue("commonUses", new String[] { "baking", "snack" });
 
     orange = new TestFruitObject();
@@ -88,7 +88,7 @@ public class MetaDataObject_implTest extends TestCase {
     orange.setAttributeValue("color", "orange");
     orange.setAttributeValue("avgWeightLbs", 0.2F);
     orange.setAttributeValue("avgCostCents", 50);
-    orange.setAttributeValue("citrus", Boolean.TRUE);
+    orange.setAttributeValue("citrus", TRUE);
     orange.setAttributeValue("commonUses", new String[] { "snack", "juice" });
 
     // create a fruit bag containing these three objects
@@ -117,75 +117,57 @@ public class MetaDataObject_implTest extends TestCase {
   /**
    * Test the getAttributes method
    */
+  @Test
   public void testGetAttributes() throws Exception {
-    try {
-      HashSet<MetaDataAttr> apple1Attrs = new HashSet<>(Arrays.asList(apple1.getAttributes()));
-      HashSet<MetaDataAttr> orangeAttrs = new HashSet<>(Arrays.asList(orange.getAttributes()));
-      HashSet<MetaDataAttr> bagAttrs = new HashSet<>(Arrays.asList(fruitBag.getAttributes()));
-      
-      Set<MetaDataAttr> r = TestFruitObject.getMetaDataAttrSet();
-      for (MetaDataAttr r1 : r) {
-        if (!apple1Attrs.contains(r1)) {
-          System.out.println("found bad one");
-        }
-      }
-      System.out.println(r.equals (apple1Attrs));
-      assertEquals(TestFruitObject.getMetaDataAttrSet(), apple1Attrs);
-      assertEquals(TestFruitObject.getMetaDataAttrSet(), orangeAttrs);
-      assertEquals(TestFruitBagObject.getMetaDataAttrSet(), bagAttrs);
-    } catch (RuntimeException e) {
-    JUnitExtension.handleException(e);
-    }
+    assertThat(apple1.getAttributes()).containsAll(TestFruitObject.getMetaDataAttrSet());
+    assertThat(orange.getAttributes()).containsAll(TestFruitObject.getMetaDataAttrSet());
+    assertThat(fruitBag.getAttributes()).containsAll(TestFruitBagObject.getMetaDataAttrSet());
   }
   
   /**
    * Tests the {@link MetaDataObject#equals(Object)} method.
    */
+  @Test
   public void testEquals() throws Exception {
-    try {
-      Assert.assertEquals(unknownFruit, unknownFruit);
-      Assert.assertEquals(apple1, apple2);
-      Assert.assertEquals(apple2, apple1);
-      Assert.assertTrue(!unknownFruit.equals(apple1));
-      Assert.assertTrue(!apple1.equals(orange));
-      Assert.assertTrue(!apple1.equals(null));
-
-      Assert.assertEquals(apple1, apple1.clone());
-      Assert.assertEquals(fruitBag, fruitBag.clone());
-      Assert.assertTrue(!apple1.equals(orange.clone()));
-      
-      // test with maps
-      ConfigurationParameterSettings cps1 = UIMAFramework.getResourceSpecifierFactory().createConfigurationParameterSettings();
-      cps1.getSettingsForGroups().put("k1", new NameValuePair[] {new NameValuePair_impl("s1", "o1")});
-      cps1.getSettingsForGroups().put("k2", new NameValuePair[] {new NameValuePair_impl("s2", "o2")});
-      ConfigurationParameterSettings cps2 = UIMAFramework.getResourceSpecifierFactory().createConfigurationParameterSettings();
-      cps2.getSettingsForGroups().put("k1", new NameValuePair[] {new NameValuePair_impl("s1", "o1")});
-      cps2.getSettingsForGroups().put("k2", new NameValuePair[] {new NameValuePair_impl("s2", "o2")});
-      
-      Assert.assertEquals(cps1, cps2);
-      Assert.assertEquals(cps1, cps2.clone());
-      
-      cps2.getSettingsForGroups().put("k2", new NameValuePair[] {new NameValuePair_impl("s2", "ox2")});
-      Assert.assertFalse(cps1.equals(cps2));
-           
-    } catch (RuntimeException e) {
-      JUnitExtension.handleException(e);
-    }
+    assertThat(unknownFruit).isEqualTo(unknownFruit);
+    assertThat(apple1).isEqualTo(apple2);
+    assertThat(apple2).isEqualTo(apple1);
+    assertThat(unknownFruit).isNotEqualTo(apple1);
+    assertThat(apple1).isNotEqualTo(orange);
+    assertThat(apple1).isNotEqualTo(null);
+
+    assertThat(apple1).isEqualTo(apple1.clone());
+    assertThat(fruitBag).isEqualTo(fruitBag.clone());
+    assertThat(apple1).isNotEqualTo(orange.clone());
+        
+    // test with maps
+    ConfigurationParameterSettings cps1 = getResourceSpecifierFactory().createConfigurationParameterSettings();
+    cps1.getSettingsForGroups().put("k1", new NameValuePair[] {new NameValuePair_impl("s1", "o1")});
+    cps1.getSettingsForGroups().put("k2", new NameValuePair[] {new NameValuePair_impl("s2", "o2")});
+    
+    ConfigurationParameterSettings cps2 = getResourceSpecifierFactory().createConfigurationParameterSettings();
+    cps2.getSettingsForGroups().put("k1", new NameValuePair[] {new NameValuePair_impl("s1", "o1")});
+    cps2.getSettingsForGroups().put("k2", new NameValuePair[] {new NameValuePair_impl("s2", "o2")});
+    
+    assertThat(cps1).isEqualTo(cps2);
+    assertThat(cps1).isEqualTo(cps2.clone());
+    
+    cps2.getSettingsForGroups().put("k2", new NameValuePair[] {new NameValuePair_impl("s2", "ox2")});
+    
+    assertThat(cps1).isNotEqualTo(cps2);
   }
 
   /**
    * Tests the {@link MetaDataObject#toString()} method.
    */
+  @Test
   public void testToString() throws Exception {
-    try {
-      String apple1Str = apple1.toString();
-      String apple2Str = apple2.toString();
-      String orangeStr = orange.toString();
-      Assert.assertEquals(apple1Str, apple2Str);
-      Assert.assertTrue(!apple1Str.equals(orangeStr));
-    } catch (RuntimeException e) {
-      JUnitExtension.handleException(e);
-    }
+    String apple1Str = apple1.toString();
+    String apple2Str = apple2.toString();
+    String orangeStr = orange.toString();
+
+    assertThat(apple1Str).isEqualTo(apple2Str);
+    assertThat(apple1Str).isNotEqualTo(orangeStr);
   }
 
   /**
@@ -194,128 +176,102 @@ public class MetaDataObject_implTest extends TestCase {
    * exercise the {@link MetaDataObject#getAttributeValue(String)} and
    * {@link MetaDataObject#setAttributeValue(String,Object)} methods.
    */
+  @Test
   public void testXMLization() throws Exception {
-    try {
-      // write objects to XML
-
-      StringWriter writer = new StringWriter();
-      apple1.toXML(writer);
-      String apple1xml = writer.getBuffer().toString();
-      // System.out.println(apple1xml);
-
-      writer = new StringWriter();
-      apple2.toXML(writer);
-      String apple2xml = writer.getBuffer().toString();
-
-      writer = new StringWriter();
-      orange.toXML(writer);
-      String orangeXml = writer.getBuffer().toString();
-
-      writer = new StringWriter();
-      fruitBag.toXML(writer);
-      String fruitBagXml = writer.getBuffer().toString();
-
-      // identical objects should have identical XML
-      Assert.assertEquals(apple1xml, apple2xml);
-
-      // parse the XML
-      DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
-      DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
-
-      Document apple1xmlDoc = docBuilder.parse(new ByteArrayInputStream(apple1xml.getBytes()));
-      Document apple2xmlDoc = docBuilder.parse(new ByteArrayInputStream(apple2xml.getBytes()));
-      Document orangeXmlDoc = docBuilder.parse(new ByteArrayInputStream(orangeXml.getBytes()));
-      Document fruitBagXmlDoc = docBuilder.parse(new ByteArrayInputStream(fruitBagXml.getBytes()));
-
-      // construct new objects from the XML
-      XMLParser xmlp = UIMAFramework.getXMLParser();
-      MetaDataObject_impl newApple1 = (MetaDataObject_impl) unknownFruit.clone();
-      newApple1.buildFromXMLElement(apple1xmlDoc.getDocumentElement(), xmlp);
-      MetaDataObject_impl newApple2 = (MetaDataObject_impl) unknownFruit.clone();
-      newApple2.buildFromXMLElement(apple2xmlDoc.getDocumentElement(), xmlp);
-      MetaDataObject_impl newOrange = (MetaDataObject_impl) unknownFruit.clone();
-      newOrange.buildFromXMLElement(orangeXmlDoc.getDocumentElement(), xmlp);
-
-      xmlp.addMapping("fruit", TestFruitObject.class.getName());
-
-      MetaDataObject_impl newFruitBag = new TestFruitBagObject();
-      newFruitBag.buildFromXMLElement(fruitBagXmlDoc.getDocumentElement(), xmlp);
-
-      // new objects should be equal to the originals
-      Assert.assertEquals(apple1, newApple1);
-      Assert.assertEquals(apple2, newApple2);
-      Assert.assertEquals(orange, newOrange);
-      Assert.assertTrue(fruitBag.equals(newFruitBag));
-
-      // test special cases
-
-      // single-property object where property name is omitted from XML
-      String xmlStr = "<fruitBag><fruit><name>banana</name><color>yellow</color></fruit>"
-              + "<fruit><name>raspberry</name><color>red</color></fruit></fruitBag>";
-      Document xmlDoc = docBuilder.parse(new ByteArrayInputStream(xmlStr.getBytes()));
-      TestFruitBagObject bag = new TestFruitBagObject();
-      bag.buildFromXMLElement(xmlDoc.getDocumentElement(), xmlp);
-      TestFruitObject[] fruits = bag.getFruits();
-      Assert.assertEquals(2, fruits.length);
-      Assert.assertEquals("banana", fruits[0].getName());
-      Assert.assertEquals("raspberry", fruits[1].getName());
-
-      // property name omitted but can be inferred from type of value
-      xmlStr = "<fruit><name>banana</name><string>yellow</string></fruit>";
-      xmlDoc = docBuilder.parse(new ByteArrayInputStream(xmlStr.getBytes()));
-      TestFruitObject banana = new TestFruitObject();
-      banana.buildFromXMLElement(xmlDoc.getDocumentElement(), xmlp);
-      Assert.assertEquals("yellow", banana.getColor());
-      Assert.assertEquals("banana", banana.getName());
-
-      // env var reference
-      xmlStr = "<fruit><name>raspberry</name><string><envVarRef>test.raspberry.color</envVarRef></string></fruit>";
-      System.setProperty("test.raspberry.color", "red");
-      xmlDoc = docBuilder.parse(new ByteArrayInputStream(xmlStr.getBytes()));
-      TestFruitObject raspberry = new TestFruitObject();
-      raspberry.buildFromXMLElement(xmlDoc.getDocumentElement(), xmlp);
-      Assert.assertEquals("red", raspberry.getColor());
-      Assert.assertEquals("raspberry", raspberry.getName());
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
-    }
+    // write objects to XML
+    String apple1xml = toXmlString(apple1);
+    String apple2xml = toXmlString(apple2);
+    String orangeXml = toXmlString(orange);
+    String fruitBagXml = toXmlString(fruitBag);
+
+    // identical objects should have identical XML
+    assertThat(apple1xml).isEqualTo(apple2xml);
+
+    // parse the XML
+    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
+
+    Document apple1xmlDoc = docBuilder.parse(new ByteArrayInputStream(apple1xml.getBytes()));
+    Document apple2xmlDoc = docBuilder.parse(new ByteArrayInputStream(apple2xml.getBytes()));
+    Document orangeXmlDoc = docBuilder.parse(new ByteArrayInputStream(orangeXml.getBytes()));
+    Document fruitBagXmlDoc = docBuilder.parse(new ByteArrayInputStream(fruitBagXml.getBytes()));
+
+    // construct new objects from the XML
+    XMLParser xmlp = UIMAFramework.getXMLParser();
+    MetaDataObject_impl newApple1 = (MetaDataObject_impl) unknownFruit.clone();
+    newApple1.buildFromXMLElement(apple1xmlDoc.getDocumentElement(), xmlp);
+    MetaDataObject_impl newApple2 = (MetaDataObject_impl) unknownFruit.clone();
+    newApple2.buildFromXMLElement(apple2xmlDoc.getDocumentElement(), xmlp);
+    MetaDataObject_impl newOrange = (MetaDataObject_impl) unknownFruit.clone();
+    newOrange.buildFromXMLElement(orangeXmlDoc.getDocumentElement(), xmlp);
+
+    xmlp.addMapping("fruit", TestFruitObject.class.getName());
+
+    MetaDataObject_impl newFruitBag = new TestFruitBagObject();
+    newFruitBag.buildFromXMLElement(fruitBagXmlDoc.getDocumentElement(), xmlp);
+
+    // new objects should be equal to the originals
+    Assert.assertEquals(apple1, newApple1);
+    Assert.assertEquals(apple2, newApple2);
+    Assert.assertEquals(orange, newOrange);
+    Assert.assertTrue(fruitBag.equals(newFruitBag));
+
+    // test special cases
+
+    // single-property object where property name is omitted from XML
+    String xmlStr = "<fruitBag><fruit><name>banana</name><color>yellow</color></fruit>"
+            + "<fruit><name>raspberry</name><color>red</color></fruit></fruitBag>";
+    Document xmlDoc = docBuilder.parse(new ByteArrayInputStream(xmlStr.getBytes()));
+    TestFruitBagObject bag = new TestFruitBagObject();
+    bag.buildFromXMLElement(xmlDoc.getDocumentElement(), xmlp);
+    TestFruitObject[] fruits = bag.getFruits();
+    Assert.assertEquals(2, fruits.length);
+    Assert.assertEquals("banana", fruits[0].getName());
+    Assert.assertEquals("raspberry", fruits[1].getName());
+
+    // property name omitted but can be inferred from type of value
+    xmlStr = "<fruit><name>banana</name><string>yellow</string></fruit>";
+    xmlDoc = docBuilder.parse(new ByteArrayInputStream(xmlStr.getBytes()));
+    TestFruitObject banana = new TestFruitObject();
+    banana.buildFromXMLElement(xmlDoc.getDocumentElement(), xmlp);
+    Assert.assertEquals("yellow", banana.getColor());
+    Assert.assertEquals("banana", banana.getName());
+
+    // env var reference
+    xmlStr = "<fruit><name>raspberry</name><string><envVarRef>test.raspberry.color</envVarRef></string></fruit>";
+    System.setProperty("test.raspberry.color", "red");
+    xmlDoc = docBuilder.parse(new ByteArrayInputStream(xmlStr.getBytes()));
+    TestFruitObject raspberry = new TestFruitObject();
+    raspberry.buildFromXMLElement(xmlDoc.getDocumentElement(), xmlp);
+    Assert.assertEquals("red", raspberry.getColor());
+    Assert.assertEquals("raspberry", raspberry.getName());
   }
 
+  @Test
   public void testSerialization() throws Exception {
-    try {
-      byte[] apple1Bytes = SerializationUtils.serialize(apple1);
-      TestFruitObject apple1a = (TestFruitObject) SerializationUtils.deserialize(apple1Bytes);
-      Assert.assertEquals(apple1, apple1a);
-
-      byte[] apple2Bytes = SerializationUtils.serialize(apple2);
-      TestFruitObject apple2a = (TestFruitObject) SerializationUtils.deserialize(apple2Bytes);
-      Assert.assertEquals(apple2, apple2a);
-
-      byte[] orangeBytes = SerializationUtils.serialize(orange);
-      TestFruitObject orange2 = (TestFruitObject) SerializationUtils.deserialize(orangeBytes);
-      Assert.assertEquals(orange, orange2);
-
-      // make sure XMLization still works
-      StringWriter sw = new StringWriter();
-      orange.toXML(sw);
-      String orange1xml = sw.getBuffer().toString();
-      sw.getBuffer().setLength(0);
-      orange2.toXML(sw);
-      String orange2xml = sw.getBuffer().toString();
-      assertEquals(orange1xml, orange2xml);
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
-    }
+    assertThat(deserialize(serialize(apple1)))
+        .isInstanceOf(TestFruitObject.class)
+        .isEqualTo(apple1);
+
+    assertThat(deserialize(serialize(apple2)))
+        .isInstanceOf(TestFruitObject.class)
+        .isEqualTo(apple2);
+
+    byte[] orangeBytes = serialize(orange);
+    assertThat(deserialize(orangeBytes))
+        .isInstanceOf(TestFruitObject.class)
+        .isEqualTo(orange);
+
+    // make sure XMLization still works
+    String orange1xml = toXmlString(orange);
+    String orange2xml = toXmlString((TestFruitObject) deserialize(orangeBytes));
+    
+    assertThat(orange1xml).isEqualTo(orange2xml);
+  }
+  
+  private String toXmlString(XMLizable aObject) throws IOException, SAXException {
+    StringWriter writer = new StringWriter();
+    aObject.toXML(writer);
+    return writer.getBuffer().toString();
   }
-
-  private TestFruitObject unknownFruit;
-
-  private TestFruitObject apple1;
-
-  private TestFruitObject apple2;
-
-  private TestFruitObject orange;
-
-  private TestFruitBagObject fruitBag;
-
 }
diff --git a/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TypeSystemDescription_implTest.java b/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TypeSystemDescription_implTest.java
index 52cbd45..b991c08 100644
--- a/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TypeSystemDescription_implTest.java
+++ b/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TypeSystemDescription_implTest.java
@@ -16,14 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.uima.resource.metadata.impl;
 
+import static java.lang.System.identityHashCode;
+import static java.util.Arrays.asList;
+import static org.apache.uima.UIMAFramework.getResourceSpecifierFactory;
+import static org.apache.uima.UIMAFramework.newDefaultResourceManager;
+import static org.apache.uima.test.junit_extension.JUnitExtension.getFile;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.junit.Assert.assertEquals;
+
 import java.io.File;
 import java.net.URL;
 
-import junit.framework.TestCase;
-
 import org.apache.uima.UIMAFramework;
 import org.apache.uima.resource.ResourceInitializationException;
 import org.apache.uima.resource.ResourceManager;
@@ -32,163 +39,162 @@ import org.apache.uima.resource.metadata.Import;
 import org.apache.uima.resource.metadata.TypeDescription;
 import org.apache.uima.resource.metadata.TypeSystemDescription;
 import org.apache.uima.test.junit_extension.JUnitExtension;
+import org.apache.uima.test.junit_extension.PrintExceptionsWhenRunFromCommandLineRule;
 import org.apache.uima.util.CasCreationUtils;
 import org.apache.uima.util.InvalidXMLException;
 import org.apache.uima.util.XMLInputSource;
+import org.apache.uima.util.XMLParser;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+public class TypeSystemDescription_implTest {
+  public @Rule TestRule exceptingHandlingRule = new PrintExceptionsWhenRunFromCommandLineRule();
+
+  private XMLParser xmlParser;
+
+  @Before
+  public void setUp() throws Exception {
+    xmlParser = UIMAFramework.getXMLParser();
+    xmlParser.enableSchemaValidation(true);
+  }
 
+  @After
+  public void tearDown() throws Exception {
+    // Note that the XML parser is a singleton in the framework, so we have to set this back to the
+    // default.
+    xmlParser.enableSchemaValidation(false);
+  }
 
-public class TypeSystemDescription_implTest extends TestCase {
-
-  /**
-   * Constructor for TypeSystemDescription_implTest.
-   * 
-   * @param arg0
-   */
-  public TypeSystemDescription_implTest(String arg0) {
-    super(arg0);
+  @Test
+  public void testBuildFromXmlElement() throws Exception {
+    File descriptor = getFile("TypeSystemDescriptionImplTest/TestTypeSystem.xml");
+    TypeSystemDescription ts = xmlParser.parseTypeSystemDescription(new XMLInputSource(descriptor));
+
+    assertThat(ts.getName()).isEqualTo("TestTypeSystem");
+    assertThat(ts.getDescription()).isEqualTo("This is a test.");
+    assertThat(ts.getVendor()).isEqualTo("The Apache Software Foundation");
+    assertThat(ts.getVersion()).isEqualTo("0.1");
+
+    assertThat(ts.getImports()).extracting(Import::getName, Import::getLocation).containsExactly(
+        tuple("org.apache.uima.resource.metadata.impl.TypeSystemImportedByName", null),
+        tuple(null, "TypeSystemImportedByLocation.xml"),
+        tuple("TypeSystemImportedFromDataPath", null));
+
+    assertThat(ts.getTypes()).extracting(TypeDescription::getName, TypeDescription::getDescription,
+        TypeDescription::getSupertypeName)
+        .containsExactly(tuple("NamedEntity", "Anything that has a name.", "uima.tcas.Annotation"),
+            tuple("Person", "A person.", "NamedEntity"), tuple("Place", "A place.", "NamedEntity"),
+            tuple("DocumentStructure",
+                "Identifies document structure, such as sentence or paragraph.",
+                "uima.tcas.Annotation"),
+            tuple("Paragraph", "A paragraph.", "DocumentStructure"),
+            tuple("Sentence", "A sentence.", "DocumentStructure"));
+
+    assertThat(ts.getTypes()[4].getFeatures())
+        .extracting(FeatureDescription::getName, FeatureDescription::getDescription,
+            FeatureDescription::getRangeTypeName, FeatureDescription::getElementType,
+            FeatureDescription::getMultipleReferencesAllowed)
+        .containsExactly(
+            tuple("sentences", "Direct references to sentences in this paragraph",
+                "uima.cas.FSArray", "Sentence", false),
+            tuple("testMultiRefAllowedFeature", "A test feature that allows multiple references.",
+                "uima.cas.FSArray", null, true));
   }
 
-  /*
-   * @see TestCase#setUp()
-   */
-  protected void setUp() throws Exception {
-    super.setUp();
-    UIMAFramework.getXMLParser().enableSchemaValidation(true);
+  @Test
+  public void testResolveImports() throws Exception {
+    File descriptor = getFile("TypeSystemDescriptionImplTest/TestTypeSystem.xml");
+    TypeSystemDescription ts = xmlParser.parseTypeSystemDescription(new XMLInputSource(descriptor));
+
+    assertThat(ts.getTypes()).as("Type count before resolving the descriptor").hasSize(6);
+
+    assertThatThrownBy(() -> ts.resolveImports()).isInstanceOf(InvalidXMLException.class);
+    assertThat(ts.getTypes()).as(
+        "Type count after resolving failed should be same as before / no side effect on exception")
+        .hasSize(6);
+
+    // set data path correctly and it should work
+    ResourceManager resMgr = newDefaultResourceManager();
+    resMgr.setDataPath(
+        JUnitExtension.getFile("TypeSystemDescriptionImplTest/dataPathDir").getAbsolutePath());
+    ts.resolveImports(resMgr);
+
+    assertThat(ts.getTypes()).as("Type count after resolving the descriptor").hasSize(13);
   }
 
-  /*
-   * @see TestCase#tearDown()
-   */
-  protected void tearDown() throws Exception {
-    super.tearDown();
+  @Test
+  public void thatCircularImportsDoNotCrash() throws Exception {
+    // test that circular imports don't crash
+    File descriptor = getFile("TypeSystemDescriptionImplTest/Circular1.xml");
+    TypeSystemDescription ts = xmlParser.parseTypeSystemDescription(new XMLInputSource(descriptor));
+    ts.resolveImports();
+    assertEquals(2, ts.getTypes().length);
   }
 
-  public void testBuildFromXmlElement() throws Exception {
-    try {
-      File descriptor = JUnitExtension.getFile("TypeSystemDescriptionImplTest/TestTypeSystem.xml");
-      TypeSystemDescription ts = UIMAFramework.getXMLParser().parseTypeSystemDescription(
-              new XMLInputSource(descriptor));
-
-      assertEquals("TestTypeSystem", ts.getName());
-      assertEquals("This is a test.", ts.getDescription());
-      assertEquals("The Apache Software Foundation", ts.getVendor());
-      assertEquals("0.1", ts.getVersion());
-      Import[] imports = ts.getImports();
-      assertEquals(3, imports.length);
-      assertEquals("org.apache.uima.resource.metadata.impl.TypeSystemImportedByName", imports[0]
-              .getName());
-      assertNull(imports[0].getLocation());
-      assertNull(imports[1].getName());
-      assertEquals("TypeSystemImportedByLocation.xml", imports[1].getLocation());
-
-      TypeDescription[] types = ts.getTypes();
-      assertEquals(6, types.length);
-      TypeDescription paragraphType = types[4];
-      assertEquals("Paragraph", paragraphType.getName());
-      assertEquals("A paragraph.", paragraphType.getDescription());
-      assertEquals("DocumentStructure", paragraphType.getSupertypeName());
-      FeatureDescription[] features = paragraphType.getFeatures();
-      assertEquals(2, features.length);
-      assertEquals("sentences", features[0].getName());
-      assertEquals("Direct references to sentences in this paragraph", features[0].getDescription());
-      assertEquals("uima.cas.FSArray", features[0].getRangeTypeName());
-      assertEquals("Sentence", features[0].getElementType());
-      assertFalse(features[0].getMultipleReferencesAllowed().booleanValue());
-
-      // ts.toXML(System.out);
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
-    }
+  @Test
+  public void thatResolveImportsDoesNothingWhenThereAreNoImports() throws Exception {
+    // calling resolveImports when there are none should do nothing
+    File descriptor = getFile("TypeSystemDescriptionImplTest/TypeSystemImportedByLocation.xml");
+
+    TypeSystemDescription ts = xmlParser.parseTypeSystemDescription(new XMLInputSource(descriptor));
+
+    assertThat(ts.getTypes()).hasSize(2);
+
+    ts.resolveImports();
+
+    assertThat(ts.getTypes()).hasSize(2);
   }
 
-  public void testResolveImports() throws Exception {
-    try {
-      File descriptor = JUnitExtension.getFile("TypeSystemDescriptionImplTest/TestTypeSystem.xml");
-      TypeSystemDescription ts = UIMAFramework.getXMLParser().parseTypeSystemDescription(
-              new XMLInputSource(descriptor));
-
-      TypeDescription[] types = ts.getTypes();
-      assertEquals(6, types.length);
-
-      // resolving imports without setting data path should fail
-      InvalidXMLException ex = null;
-      try {
-        ts.resolveImports();
-      } catch (InvalidXMLException e) {
-        ex = e;
-      }
-      assertNotNull(ex);
-      assertEquals(6, ts.getTypes().length); // should be no side effects when exception is thrown
-
-      // set data path correctly and it should work
-      ResourceManager resMgr = UIMAFramework.newDefaultResourceManager();
-      resMgr.setDataPath(JUnitExtension.getFile("TypeSystemDescriptionImplTest/dataPathDir")
-              .getAbsolutePath());
-      ts.resolveImports(resMgr);
-
-      types = ts.getTypes();
-      assertEquals(13, types.length);
-      
-      // test that circular imports don't crash
-      descriptor = JUnitExtension.getFile("TypeSystemDescriptionImplTest/Circular1.xml");
-      ts = UIMAFramework.getXMLParser().parseTypeSystemDescription(new XMLInputSource(descriptor));
-      ts.resolveImports();
-      assertEquals(2, ts.getTypes().length);
-
-      // calling resolveImports when there are none should do nothing
-      descriptor = JUnitExtension
-              .getFile("TypeSystemDescriptionImplTest/TypeSystemImportedByLocation.xml");
-      ts = UIMAFramework.getXMLParser().parseTypeSystemDescription(new XMLInputSource(descriptor));
-      assertEquals(2, ts.getTypes().length);
-      ts.resolveImports();
-      assertEquals(2, ts.getTypes().length);
-
-      // test import from programatically created TypeSystemDescription
-      TypeSystemDescription typeSystemDescription = UIMAFramework.getResourceSpecifierFactory()
-              .createTypeSystemDescription();
-      Import[] imports = new Import[1];
-      imports[0] = new Import_impl();
-      URL url = JUnitExtension.getFile("TypeSystemDescriptionImplTest").toURL();
-      ((Import_impl) imports[0]).setSourceUrl(url);
-      imports[0].setLocation("TypeSystemImportedByLocation.xml");
-      typeSystemDescription.setImports(imports);
-      TypeSystemDescription typeSystemWithResolvedImports = (TypeSystemDescription) typeSystemDescription
-              .clone();
-      typeSystemWithResolvedImports.resolveImports(resMgr);
-      assertTrue(typeSystemWithResolvedImports.getTypes().length > 0);      
-    
-      //test that importing the same descriptor twice (using the same ResourceManager) caches
-      //the result of the first import and does not create new objects
-      TypeSystemDescription typeSystemDescription2 = UIMAFramework.getResourceSpecifierFactory()
-      .createTypeSystemDescription();
-        Import[] imports2 = new Import[1];
-      imports2[0] = new Import_impl();
-      ((Import_impl) imports2[0]).setSourceUrl(url);
-      imports2[0].setLocation("TypeSystemImportedByLocation.xml");
-      typeSystemDescription2.setImports(imports2);
-      TypeSystemDescription typeSystemWithResolvedImports2 = (TypeSystemDescription) typeSystemDescription2
-              .clone();
-      typeSystemWithResolvedImports2.resolveImports(resMgr);
-      for (int i = 0 ; i < typeSystemWithResolvedImports.getTypes().length; i++) {
-        assertTrue(typeSystemWithResolvedImports.getTypes()[i] == typeSystemWithResolvedImports2.getTypes()[i]);
-      }
-
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
-    }        
+  @Test
+  public void thatImportFromProgrammaticallyCreatedTypeSystemDescriptionWorks() throws Exception {
+    ResourceManager resMgr = newDefaultResourceManager();
+    URL url = getFile("TypeSystemDescriptionImplTest").toURL();
+
+    // test import from programatically created TypeSystemDescription
+    Import_impl[] imports = { new Import_impl() };
+    imports[0].setSourceUrl(url);
+    imports[0].setLocation("TypeSystemImportedByLocation.xml");
+
+    TypeSystemDescription typeSystemDescription = getResourceSpecifierFactory()
+        .createTypeSystemDescription();
+    typeSystemDescription.setImports(imports);
+    TypeSystemDescription typeSystemWithResolvedImports = (TypeSystemDescription) typeSystemDescription
+        .clone();
+    typeSystemWithResolvedImports.resolveImports(resMgr);
+
+    assertThat(typeSystemWithResolvedImports.getTypes()).isNotEmpty();
+
+    // test that importing the same descriptor twice (using the same ResourceManager) caches
+    // the result of the first import and does not create new objects
+    TypeSystemDescription typeSystemDescription2 = getResourceSpecifierFactory()
+        .createTypeSystemDescription();
+
+    Import_impl[] imports2 = { new Import_impl() };
+    imports2[0].setSourceUrl(url);
+    imports2[0].setLocation("TypeSystemImportedByLocation.xml");
+
+    typeSystemDescription2.setImports(imports2);
+    TypeSystemDescription typeSystemWithResolvedImports2 = (TypeSystemDescription) typeSystemDescription2
+        .clone();
+    typeSystemWithResolvedImports2.resolveImports(resMgr);
+
+    assertThat(typeSystemWithResolvedImports.getTypes())
+        .as("Resolved imports in second type system are the same as in the first (cached)")
+        .usingElementComparator((a, b) -> identityHashCode(a) - identityHashCode(b))
+        .containsExactlyElementsOf(asList(typeSystemWithResolvedImports2.getTypes()));
   }
 
+  @Test
   public void testInvalidTypeSystem() throws Exception {
-    File file = JUnitExtension.getFile("TypeSystemDescriptionImplTest/InvalidTypeSystem1.xml");
-    TypeSystemDescription tsDesc = UIMAFramework.getXMLParser().parseTypeSystemDescription(
-            new XMLInputSource(file));
-    try {
-      CasCreationUtils.createCas(tsDesc, null, null);
-      // the above line should throw an exception
-      fail();
-    } catch (ResourceInitializationException e) {
-      assertNotNull(e.getMessage());
-      assertFalse(e.getMessage().startsWith("EXCEPTION MESSAGE LOCALIZATION FAILED"));
-    }
+    File file = getFile("TypeSystemDescriptionImplTest/InvalidTypeSystem1.xml");
+
+    TypeSystemDescription tsDesc = xmlParser.parseTypeSystemDescription(new XMLInputSource(file));
+
+    assertThatThrownBy(() -> CasCreationUtils.createCas(tsDesc, null, null))
+        .isInstanceOf(ResourceInitializationException.class)
+        .hasMessageContaining("uima.cas.String");
   }
 }
diff --git a/uimaj-test-util/src/main/java/org/apache/uima/test/junit_extension/PrintExceptionsWhenRunFromCommandLineRule.java b/uimaj-test-util/src/main/java/org/apache/uima/test/junit_extension/PrintExceptionsWhenRunFromCommandLineRule.java
new file mode 100644
index 0000000..edd2932
--- /dev/null
+++ b/uimaj-test-util/src/main/java/org/apache/uima/test/junit_extension/PrintExceptionsWhenRunFromCommandLineRule.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.uima.test.junit_extension;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+public class PrintExceptionsWhenRunFromCommandLineRule
+    implements TestRule
+{
+
+    @Override
+    public Statement apply(Statement aBase, Description aDescription)
+    {
+        return new Statement()
+        {
+            @Override
+            public void evaluate() throws Throwable
+            {
+                try {
+                    aBase.evaluate();
+                }
+                catch (Exception e) {
+                    JUnitExtension.handleException(e);
+                }
+            }
+        };
+    }
+}