= Unit Test Support

:Notice: 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.

Apache Isis provides a number of helpers to help unit test your domain objects.


== Maven Configuration

include::docs:mavendeps:partial$setup-and-configure-dependencyManagement.adoc[leveloffset=+2]

In addition, add a section for the BOM of all the testing support libraries:

[source,xml,subs="attributes+"]
.pom.xml
----
<dependencyManagement>
    <dependencies>
        <dependency>
        	<groupId>org.apache.isis.testing</groupId>
	        <artifactId>isis-testing</artifactId>
            <scope>import</scope>
            <type>pom</type>
            <version>{page-isisrel}</version>
        </dependency>
    </dependencies>
</dependencyManagement>
----

[#dependencies]
=== Dependencies

In the domain module(s) of your application, add the following dependency:

[source,xml]
.pom.xml
----
<dependencies>
    <dependency>
        <groupId>org.apache.isis.testing</groupId>
        <artifactId>isis-testing-unittestsupport-applib</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
----


We also highly recommend using the xref:fakedata:about.adoc[Fakedata] library for random values in your tests:

[source,xml]
.pom.xml
----
<dependencies>
    <dependency>
        <groupId>org.apache.isis.testing</groupId>
        <artifactId>isis-testing-fakedata-applib</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
----


include::testing:ROOT:partial$surefire-configuration-caution.adoc[]


=== Update AppManifest

In your application's `AppManifest` (top-level Spring `@Configuration` used to bootstrap the app), import the `IsisModuleTestingUnitTestSupportApplib` module:

[source,java]
.AppManifest.java
----
@Configuration
@Import({
        ...
        IsisModuleTestingUnitTestSupportApplib.class,
        ...
})
public class AppManifest {
}
----

(In fact, this is optional; the classes in the unit test support library can be used outside of a running application).

== PojoTester

The xref:refguide:testing:index/unittestsupport/applib/dom/pojo/PojoTester.adoc[PojoTester] utility automates the testing of getters and setters.

As getters and setters are so simple, the intention of automating their testing is not to discover defects (though if there are unintentional side-effects, then these will be found).
Instead, the rationale of testing getters and setters is to increase code coverage.
Any substantial gap away from 100% would therefore due to significant functionality not having tests (as opposed to merely getters and setters not being tested).

The class has built-in support for primitives and most of the other value types already recognised by the framework, and provides a mechanism to allow example instances for any application-specific types.

For example, given a class:

[source,java]
.Customer.java
----
@Getter @Setter
public class Customer {
    private int custNum;
    private String name;
    private Date registeredOn;
    private Address address;
    private List<Order> orders;
}
----

then all of the getters and setters can be exercised using:

[source,java]
.Customer_Test.java
----
public class Customer_Test {

    @Test
    void exercise_getters_and_setters() {
        PojoTester.create()
            .usingData(Address.class, Address.class)    // <.>
            .usingData(Order.class, Order.class)        // <1>
            .exercise();
    }
}
----

<.> provides the compile-time and run-time types of the referenced objects.
The runtime-type must provide a no-arg constructor.
+
In many cases (as here) the same type can be used for both parameters.

There are several overloads of the `usingData(...)` method, one of which accepts a `PojoTester.DatumFactory` instance.
This interface provides a more flexible way to provide arbitrary datum instances for a specified type.


== Contract Tests

Contract tests ensure that all instances of a particular idiom/pattern that occur within your codebase are implemented correctly.
You could think of them as being a way to enforce a certain type of coding standard.


=== ``SortedSet``s

This contract test automatically checks that all fields of type `java.util.Collection` are declared as `java.util.SortedSet`.
In other words, it precludes either `java.util.List` or `java.util.Set` from being used as a collection.

For example, the following passes the contract test:

[source,java]
----
public class Department {
    private SortedSet<Employee> employees = new TreeSet<Employee>();
    ...
}
----

whereas this would not:

[source,java]
----
public class SomeDomainObject {
    private List<Employee> employees = new ArrayList<Employee>();
    ...
}
----

To use the contract test, subclass `SortedSetsContractTestAbstract`, specifying the root package to search for domain classes.

For example:

[source,java]
----
public class SortedSetsContractTestAll extends SortedSetsContractTestAbstract {

    public SortedSetsContractTestAll() {
        super("com.mycompany.myapp.modules");
        withLoggingTo(System.out);
    }
}
----


If using an RDBMS for persistence then we strongly recommend that you implement this test, for several reasons:

* first, ``Set``s align more closely to the relational model than do ``List``s.
A ``List`` must have an additional index to specify order.

* second, `SortedSet` is preferable to `Set` because then the order is well-defined and predictable (to an end user, to the programmer).
+
The xref:refguide:applib:index/util/ObjectContracts.adoc[ObjectContracts]  utility class substantially simplifies the task of implementing `Comparable` in your domain classes.

* third, if the relationship is bidirectional then the ORM (JDO/DataNucleus) will automatically maintain the relationship.




=== Comparable

TODO
ComparableContractTest_compareTo


=== Value Objects

The xref:refguide:testing:index/unittestsupport/applib/dom/value/ValueTypeContractTestAbstract.adoc[ValueTypeContractTestAbstract] tests that a custom value type implements `equals()` and `hashCode()` correctly.

For example, testing JDK's own `java.math.BigInteger` can be done as follows:

[source,java]
----
public class ValueTypeContractTestAbstract_BigIntegerTest extends ValueTypeContractTestAbstract<BigInteger> {

    @Override
    protected List<BigInteger> getObjectsWithSameValue() {      // <.>
        return Arrays.asList(new BigInteger("1"), new BigInteger("1"));
    }

    @Override
    protected List<BigInteger> getObjectsWithDifferentValue() { // <.>
        return Arrays.asList(new BigInteger("2"));
    }
}
----

<.> Returns a list of different instances that are expected to have the same value (according to equals and hashCode).
<.> Returns a list of instances that are different from each other and also from the instance(s) provided in the `getObjectsWithSameValue()` method.
As here, it is often sufficient to provide a single instance (as it is compared against the instances provided by `getObjectsWithSameValue()`.




=== XML Marshalling Support

Apache Isis' unit testing support provides the xref:refguide:testing:index/unittestsupport/applib/matchers/JaxbMatchers.adoc[JaxbMatchers] while the core applib also provides the useful xref:refguide:applib:index/util/JaxbUtil.adoc[JaxbUtil] class.

These can be useful for example if you have example XML-serialized representations of the SOAP requests and response payloads and want to use these within your tests.




== JMock Extensions

[WARNING]
====
The JMock extensions are deprecated; we suggest you use Mockito instead.
====

If you use mocking, then  usual given/when/then format gets an extra step:

* *given* the system is in this state
* *expecting* these interactions (set up the mock expectations here)
* *when* I poke it with a stick
* *then* these state changes and interactions with Mocks should have occurred.

If using JMock then the interactions (in the "then") are checked automatically by a JUnit rule.
However, you probably will still have some state changes to assert upon.


Apache Isis' unit test support provides `JUnitRuleMockery2` which is an extension to the link:http://www.jmock.org/[JMock]'s `JunitRuleMockery`.
It provides a simpler API and also providing support for autowiring.


For example, here we see that the class under test, an instance of `CollaboratingUsingSetterInjection`, is automatically wired up with its `Collaborator`:

[source,java]
----
public class JUnitRuleMockery2Test_autoWiring_setterInjection_happyCase {

    @Rule
    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);

    @Mock
    private Collaborator collaborator;

    @ClassUnderTest
    private CollaboratingUsingSetterInjection collaborating;

    @Test
    public void wiring() {
        assertThat(collaborating.collaborator, is(not(nullValue())));
    }
}
----

[TIP]
.Distinguish between queries vs mutators
====
For mock interactions that simply retrieve some data, your test should not need to verify that it occurred.
If the system were to be refactored and starts caching some data, you don't really want your tests to start breaking because they are no longer performing a query that once they did.
If using JMock API this means using the `allowing(..)` method to set up the expectation.

On the other hand mocks that mutate the state of the system you probably should assert have occurred.
If using JMock this typically means using the `oneOf(...)` method.

For more tips on using JMock and mocking in general, check out the link:http://www.growing-object-oriented-software.com/[GOOS] book, written by JMock's authors, Steve Freeman and Nat Pryce and also link:http://natpryce.com/articles.html[Nat's blog].
====


== Utilities classes

The unittestsupport library also includes a number of miscellaneous utilities classes:

* xref:refguide:testing:index/unittestsupport/applib/util/CollectUtils.adoc[CollectUtils]
* xref:refguide:testing:index/unittestsupport/applib/util/FileUtils.adoc[FileUtils]
* xref:refguide:testing:index/unittestsupport/applib/util/InjectUtils.adoc[InjectUtils]
* xref:refguide:testing:index/unittestsupport/applib/util/ReflectUtils.adoc[ReflectUtils]
* xref:refguide:testing:index/unittestsupport/applib/util/StringUtils.adoc[StringUtils]


