In the context of the Pineapple project, a unit test is an isolated test of a single class. Mocking is often used to satisfy dependencies to other classes. Dependencies are often injected into the class under test.
To write unit test do:
To use the functionality of the pineapple-test-utils project, add the Maven dependency to the project POM:
<dependency> <groupId>${pom.groupId}</groupId> <artifactId>pineapple-test-utils</artifactId> </dependency>
Version information is located in the pineapple-project/pom.xml. The dependency should be scoped with test as we will only use it to write unit tests.
To use JUnit to write test cases, add the Maven dependency to the project POM:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency>
Version information is located in the pineapple-project/pom.xml. The dependency should be scoped with test as we will only use it to write unit tests.
To use EasyMock to write mock objects, add the Maven dependency to the project POM:
<dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <scope>test</scope> </dependency>
Version information is located in the pineapple-project/pom.xml. The dependency should be scoped with test as we will only use it to write unit tests.
The Spring-test jar gives access to:
To use the Spring framework test facilities, add the Maven dependency to the project POM:
<dependency> <groupId>org.springframework</groupId> <artifactId>org.springframework.test</artifactId> <scope>test</scope> </dependency>
Version information is located in the pineapple-project/pom.xml. The dependency should be scoped with test as we will only use it to write unit tests.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.alpha.pineapple</groupId> <artifactId>pineapple-modules</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>pineapple-helloworld-plugin</artifactId> <packaging>jar</packaging> <name>Pineapple Hello World plugin</name> <url>http://maven.apache.org</url> <dependencies> <!-- pineapple internal dependencies --> <dependency> <groupId>${pom.groupId}</groupId> <artifactId>pineapple-test-utils</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>${pom.groupId}</groupId> <artifactId>pineapple-api</artifactId> </dependency> <dependency> <groupId>${pom.groupId}</groupId> <artifactId>pineapple-commands-api</artifactId> </dependency> <!-- external dependencies --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>org.springframework.test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> <!-- provides access to @resource annotation --> <dependency> <groupId>javax.annotation</groupId> <artifactId>jsr250-api</artifactId> </dependency> </dependencies> .... </project>
The unit test cases are placed in the src/test/java folder.
Test classes are named XxxTest where Xxx is the name of the class which is integration tested.
Example: The unit test class for the class TestDeployedConfiguration should be named TestDeployedConfigurationTest.
Classes under test which uses annotation based dependency injection from Spring, should use the ReflectionTestUtils class to initialize annotated fields before tests are run.
Examples of annotations which is used for annotation based dependency injection in conjunction with the Spring framework are @Autowired and @Resource. The annotations are defined on class fields and directs Spring to inject dependencies when objects are initialized by the framework. To use the ReflectionTestUtils helper to initialize the annotated fields:
Example: The class TestDeployedConfiguration in the pineapple-helloworld-plugin project, could have a field named director which is annotated with the @Resource annotation:
package com.alpha.pineapple.plugin.helloworld.operation; import javax.annotation.Resource; @PluginOperation( OperationNames.TEST_DEPLOYED_CONFIGURATION ) public class TestDeployedConfiguration implements Operation { /** * XMLBeans model traversal object for this operation. */ @Resource( name = "testDeployedConfigurationTraversalDirector" ) TraversalDirector director; // remaining implementation here }
The field is initialized in the setUp() method in the unit test class:
public class TestDeployedConfigurationTest { /** * Object under test. */ TestDeployedConfiguration operation; /** * mock traversal director. */ TraversalDirector director; @Before public void setUp() throws Exception { // create mock director director = EasyMock.createMock( TraversalDirector.class ); // inject context visitor into operation ReflectionTestUtils.setField( operation, "director", director, TraversalDirector.class ); } // test methods goes here }
The behavior of a used mock object should specified either in the setUp() method or in the individual test method. Specify the behavior in the setUp() method is the object behaves the same in all tests.
Below is an example showing the specification of a TraversalDirector mock object in a test method:
@Test public void testSomething() { // some test setup goes here // complete director mock object setup EasyMock.expect( director.getVisitor()).andReturn( visitor ); EasyMock.expect( director.getVisitor()).andReturn( visitor ); director.traverse( (TraversalPair) EasyMock.isA( TraversalPair.class ) ); EasyMock.expectLastCall().andAnswer(answer); EasyMock.expect( director.getVisitor()).andReturn( visitor ); EasyMock.replay( director ); // complete another mock object setup // invoke the object under test operation.execute( content, session, null ); // test // verify mock objects EasyMock.verify( director ); EasyMock.verify( session ); EasyMock.verify( domainMbean ); }
If the projects doesn't define any log4j.properties>> in <<<src/java/resources/log4.properties then the pineapple-test-utils project contains a log4j configuration file defined in the directory src/java/resources/log4.properties for use by dependent projects as part of their test configuration.
The test configuration configures Log4j to write log files to ${user.home}/.pineapple/logs/pineapple-.log.