Versions Compared

Key

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

...

We can consider two types of classes when developing the unit tests: classes which have a dependency on the database and classes that don't. The classes that don't can be tested easily, using standard procedures and tests. Our main problem are classes tighly coupled with the database and its helper objects, like BitstreamFormat or the classes that inherit from DSpaceObject. This section focussing on To run the unit tests means we need a database but we don't have any database available, which in turn means we would not be able to test some of the methods. We have the following options:

* Ignore the methods

* Create some mocks for the database and helper objects

The second option is prefered, although the fact we are using mocks means we won't have errors as we will be getting a constant valid result. At this point there is a choice: we can create big standard mock objects (with fixed output) to be used in all our tests, or we can create custom mocks for every test. The first option means we won't be able to test error cases as the output will be always the same for a given mocked call in a mocked object. The second option ties our mocks to the current implementation of the method, as we would need to create specific mocks for the methods called from the method we are testing.

...

want to set up a standard PostgreSQL instance. Our decision is to use an in-memory database that will be used to emualte PostgreSQL.

To achive this we mock DatabaseManager and we replace the connector to point to our in-memory database. In this clase we also initialise the replica with the proper data.

Structure

There is a base class called "AbstractUnitTest". This class contains a series of mocks and references which are necessary to run the tests in DSpace, like mocks of the Context DatabaseManager object. All Unit Tests should inherit this class, located under the package "org.dspace" in the test folder of DSpace-api.

About the implementation, several objects only offer a hidden constructor and a factory method to create an instance of the object. As this factory method depends on the database, we can't rely on it to create instances of our objects. The Reflection API has been used to create the required instances for the unit tests..

DDL Utils

A Data Definition Language (DDL) is a computer language for defining data structures. This allows you, for example, to replicate the structure of one database in many other instances. We use DDLUtils asa mechanism to extract the data from PostgreSQL and repliacte it into our in-memory database.

To create the DDL files do the following steps:

  • Download DDL Utils and unzip the file
  • Download the JDBC drivers used to connect to your database and copy the libraries to the lib folder of DDLUitls
  • Create a build.xml file with the code below (change as rquired the data on the database)
    Code Block
    
    <project name="DDL" default="database-dump" basedir=".">
    
    <path id="runtime-classpath">
      <fileset dir="lib">
        <include name="**/*.jar"/>
        <include name="**/*.zip"/>
      </fileset>
    </path>
    
    <target name="database-dump" description="Dumps the database structure">
      <taskdef name="databaseToDdl"
               classname="org.apache.ddlutils.task.DatabaseToDdlTask">
        <classpath refid="runtime-classpath"/>
      </taskdef>
      <databaseToDdl modelName="DSpace" schemapattern="%" databasetype="postgresql">
        <database url="jdbc:postgresql://localhost:5432/dspace"
                  driverClassName="org.postgresql.Driver"
                  username="dspace"
                  password="dspace"/>
    
        <writeSchemaToFile outputFile="db-schema.xml"/>
        <writeDataToFile outputFile="data.xml" determineschema="true"/>
      </databaseToDdl>
    
    </target>
    </project>
    
    * Run the main task with the command:
    Code Block
    
    > ant
    
    This will genetare two files, db-schema.xml which contains the structure and data.xml which contains the data of the tables. We will use these files to replicate the database in the in-memory database.

In-Memory Database

DDL Utils has some limitations on the databases it can connect to. As a result, the choices of in-memory databases are a bit limited. We have decided to use HSQLDB, an open-source and very tested database that recently has released version 2. The database we will use is an in-memory instance, which has no persistence beyond the JVM process that manages it. Once shutdown, all the information will be erased, which makes it a perfect choice for unit testing.

  • Driver: org.hsqldb.jdbc.JDBCDriver
  • JDBC Connector: jdbc:hsqldb:mem:<database> (user: SA , password: <blank>)

To load the DDL created above we

Code Issues

During the development To summarise, the following issues have been detected in the code, which make Unit Testing harder and impact the maintability of the code:

...