/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.Properties;
import java.util.TimeZone;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.core.I18nUtil;
import org.dspace.discovery.MockIndexEventConsumer;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.servicemanager.DSpaceKernelImpl;
import org.dspace.servicemanager.DSpaceKernelInit;
import org.dspace.storage.rdbms.MockDatabaseManager;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
/**
* This is the base class for Unit Tests. It contains some generic mocks and
* utilities that are needed by most of the unit tests developed for DSpace.
*
* @author pvillega
*/
public class AbstractUnitTest
{
/** log4j category */
private static final Logger log = Logger.getLogger(AbstractUnitTest.class);
//Below there are static variables shared by all the instances of the class
/**
* Test properties.
*/
protected static Properties testProps;
//Below there are variables used in each test
/**
* Context mock object to use in the tests.
*/
protected Context context;
/**
* EPerson mock object to use in the tests.
*/
protected EPerson eperson;
protected static DSpaceKernelImpl kernelImpl;
/**
* This method will be run before the first test as per @BeforeClass. It will
* initialize resources required for the tests.
*
* Due to the way Maven works, unit tests can't be run from a POM package,
* which forbids us to run the tests from the Assembly and Configuration
* package. On the other hand we need a structure of folders to run the tests,
* like "solr", "report", etc. This will be provided by a JAR assembly
* built out of files from various modules -- see the dspace-parent POM.
*
* This method will load a few properties for derived test classes.
*
* The ConfigurationManager will be initialized to load the test
* "dspace.cfg".
*/
@BeforeClass
public static void initOnce()
{
try
{
//set a standard time zone for the tests
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Dublin"));
//load the properties of the tests
testProps = new Properties();
URL properties = AbstractUnitTest.class.getClassLoader()
.getResource("test-config.properties");
testProps.load(properties.openStream());
//load the test configuration file
ConfigurationManager.loadConfig(null);
// Initialise the service manager kernel
kernelImpl = DSpaceKernelInit.getKernel(null);
if (!kernelImpl.isRunning())
{
kernelImpl.start(ConfigurationManager.getProperty("dspace.dir"));
}
// Applies/initializes our mock database by invoking its constructor
// (NOTE: This also initializes the DatabaseManager, which in turn
// calls DatabaseUtils to initialize the entire DB via Flyway)
new MockDatabaseManager();
// Initialize a mock indexer (which does nothing, since Solr isn't running)
new MockIndexEventConsumer();
}
catch (IOException ex)
{
log.error("Error initializing tests", ex);
fail("Error initializing tests");
}
}
/**
* This method will be run before every test as per @Before. It will
* initialize resources required for the tests.
*
* Other methods can be annotated with @Before here or in subclasses
* but no execution order is guaranteed
*/
@Before
public void init()
{
try
{
//Start a new context
context = new Context();
context.turnOffAuthorisationSystem();
//Find our global test EPerson account. If it doesn't exist, create it.
eperson = EPerson.findByEmail(context, "test@email.com");
if(eperson == null)
{
// This EPerson creation should only happen once (i.e. for first test run)
log.info("Creating initial EPerson (email=test@email.com) for Unit Tests");
eperson = EPerson.create(context);
eperson.setFirstName("first");
eperson.setLastName("last");
eperson.setEmail("test@email.com");
eperson.setCanLogIn(true);
eperson.setLanguage(I18nUtil.getDefaultLocale().getLanguage());
// actually save the eperson to unit testing DB
eperson.update();
}
// Set our global test EPerson as the current user in DSpace
context.setCurrentUser(eperson);
// If our Anonymous/Administrator groups aren't initialized, initialize them as well
Group.initDefaultGroupNames(context);
context.restoreAuthSystemState();
context.commit();
}
catch (AuthorizeException ex)
{
log.error("Error creating initial eperson or default groups", ex);
fail("Error creating initial eperson or default groups in AbstractUnitTest init()");
}
catch (SQLException ex)
{
log.error(ex.getMessage(),ex);
fail("SQL Error on AbstractUnitTest init()");
}
}
/**
* This method will be run after every test as per @After. It will
* clean resources initialized by the @Before methods.
*
* Other methods can be annotated with @After here or in subclasses
* but no execution order is guaranteed
*/
@After
public void destroy()
{
// Cleanup our global context object
cleanupContext(context);
}
/**
* This method will be run after all tests finish as per @AfterClass. It will
* clean resources initialized by the @BeforeClass methods.
*
*/
@AfterClass
public static void destroyOnce()
{
//we clear the properties
testProps.clear();
testProps = null;
//Also clear out the kernel & nullify (so JUnit will clean it up)
if (kernelImpl!=null)
kernelImpl.destroy();
kernelImpl = null;
}
/**
* This method checks the configuration for Surefire has been done properly
* and classes that start with Abstract are ignored. It is also required
* to be able to run this class directly from and IDE (we need one test)
*/
/*
@Test
public void testValidationShouldBeIgnored()
{
assertTrue(5 != 0.67) ;
}
*/
/**
* This method expects and exception to be thrown. It also has a time
* constraint, failing if the test takes more than 15 ms.
*/
/*
@Test(expected=java.lang.Exception.class, timeout=15)
public void getException() throws Exception
{
throw new Exception("Fail!");
}
*/
/**
* Utility method to cleanup a created Context object (to save memory).
* This can also be used by individual tests to cleanup context objects they create.
*/
protected void cleanupContext(Context c)
{
// If context still valid, abort it
if(c!=null && c.isValid())
c.abort();
// Cleanup Context object by setting it to null
if(c!=null)
c = null;
}
}