All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jars.nosqlunit-documentation.1.0.0.source-code.introduction.xml Maven / Gradle / Ivy

The newest version!
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.0" xml:id="introduction" xmlns="http://docbook.org/ns/docbook"
	xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"
	xmlns:svg="http://www.w3.org/2000/svg" xmlns:m="http://www.w3.org/1998/Math/MathML"
	xmlns:html="http://www.w3.org/1999/xhtml" xmlns:db="http://docbook.org/ns/docbook">

	<title>NoSQLUnit Core</title>

	<section>
		<inlinemediaobject>
			<imageobject>
				<imagedata fileref="fig/nosqlunitlogo.png" />
			</imageobject>
		</inlinemediaobject>

		<title>Overview</title>

		<para>
			Unit testing is a method by which the smallest testable part of an
			application is validated. Unit tests must follow the
			<acronym>FIRST</acronym>
			Rules; these are Fast, Isolated, Repeatable,
			Self-Validated and
			Timely.
		</para>

		<para>
			It is strange to think about a
			<acronym>JEE</acronym>
			application
			without persistence layer (typical Relational databases or
			new
			<emphasis>NoSQL</emphasis>
			databases) so should be interesting to write
			unit tests of persistence
			layer too. When we are writing unit tests of
			persistence layer we
			should focus on to not break two main concepts
			of
			<acronym>FIRST</acronym>
			rules, the fast and the isolated ones.
		</para>

		<para>
			Our tests will be
			<emphasis>fast</emphasis>
			if they don't access
			network nor filesystem, and in case of
			persistence systems network and
			filesystem are the most used
			resources. In case of
			<acronym>RDBMS</acronym>
			(
			<emphasis>SQL</emphasis>
			), many Java in-memory
			databases exist like
			<application>Apache Derby</application>
			,
			<application>H2</application>
			or
			<application>HSQLDB</application>
			. These
			databases, as their name suggests are embedded into your
			program and data
			are stored in memory, so your tests are still fast.
			The problem is with
			<emphasis>NoSQL</emphasis>
			systems, because of their heterogeneity. Some
			systems work using
			Document approach (like
			<application>MongoDb</application>
			), other ones Column (like
			<application>Hbase</application>
			), or Graph (like
			<application>Neo4J</application>
			). For this reason the in-memory mode
			should be provided by the
			vendor, there is no a generic solution.
		</para>

		<para>
			Our tests must be isolated from themselves. It is not acceptable
			that
			one test method modifies the result of another test method. In case
			of persistence tests this scenario occurs when previous test method
			insert
			an entry to database and next test method execution finds the
			change.
			So
			before execution of each test, database should be found in a
			known state.
			Note that if your test found database in a known state,
			test will be
			repeatable, if test assertion depends on previous test
			execution, each
			execution will be unique. For homogeneous systems like
			<acronym>RDBMS</acronym>
			,
			<emphasis>DBUnit</emphasis>
			exists to maintain
			database in a known state before each execution.
			But there is no like
			<emphasis>DBUnit</emphasis>
			framework for heterogeneous
			<emphasis>NoSQL</emphasis>
			systems.
		</para>

		<para>
			<emphasis role="bold">NoSQLUnit</emphasis>
			resolves this problem by
			providing a
			<emphasis>JUnit</emphasis>
			extension which helps us to manage
			lifecycle of NoSQL systems and also
			take care of maintaining databases
			into known state.
		</para>
	</section>

	<section>
		<title>Requirements</title>

		<para>
			To run
			<emphasis role="bold">NoSQLUnit</emphasis>
			,
			<emphasis>JUnit
				4.10
			</emphasis>
			or later must be provided. This is because of
			<emphasis role="bold">NoSQLUnit</emphasis>
			is using
			<emphasis>Rules</emphasis>
			, and
			they have changed from previous versions to 4.10.
		</para>

		<para>
			Although it should work with
			<acronym>JDK 5</acronym>
			, jars are
			compiled using
			<acronym>JDK 6</acronym>
			.
		</para>
	</section>

	<section>
		<title>NoSQLUnit</title>

		<para>
			<emphasis role="bold">NoSQLUnit</emphasis>
			is a
			<emphasis>JUnit</emphasis>
			extension to make writing unit and integration
			tests of systems that
			use NoSQL backend easier and is composed by two sets
			of
			<emphasis>Rules</emphasis>
			and a group of annotations.
		</para>

		<para>
			First set of
			<emphasis>Rules</emphasis>
			are those responsible of
			managing database lifecycle; there are two
			for each supported
			backend.
		</para>

		<itemizedlist>
			<listitem>
				<para>
					The first one (in case it is possible) it is the
					<emphasis role="bold">in-memory</emphasis>
					mode. This mode takes care of
					starting and stopping database system
					in
					"
					<emphasis>in-memory</emphasis>
					" mode. This mode will be typically
					used during unit testing
					execution.
				</para>
			</listitem>

			<listitem>
				<para>
					The second one is the
					<emphasis role="bold">managed</emphasis>
					mode. This mode is in charge of starting
					<emphasis>NoSQL</emphasis>
					server but as remote process (in local machine) and stopping it.
					This
					will typically used during integration testing execution.
				</para>
			</listitem>
		</itemizedlist>

		<para>
			Second set of
			<emphasis>Rules</emphasis>
			are those responsible of
			maintaining database into known state. Each
			supported backend will have
			its own, and can be understood as a
			connection to defined database which
			will be used to execute the
			required operations for maintaining the
			stability of the system.
		</para>

		<para>
			Note that because
			<emphasis>NoSQL</emphasis>
			databases are
			heterogeneous, each system will require its own
			implementation.
		</para>

		<para>
			And finally two annotations are provided,
			<link linkend="seeding_database">@UsingDataSet</link>
			and
			<link linkend="verifying_database">@ShouldMatchDataSet</link>
			, (thank you so
			much
			<emphasis>Arquillian</emphasis>
			people for the name).
		</para>

		<section>
			<title xml:id="seeding_database">Seeding Database</title>

			<para>
				@UsingDataSet is used to seed database with defined data set. In
				brief data sets are files that contain all data to be inserted to
				configured database. In order to seed your database, use
				<emphasis>@UsingDataSet</emphasis>
				annotation, you can define it either
				on the test itself or on the
				class level. If there is definition on
				both, test level annotation
				takes precedence. This annotation has
				two
				attributes
				<methodname>locations</methodname>
				and
				<methodname>loadStrategy</methodname>
				.
			</para>

			<para>
				With
				<methodname>locations</methodname>
				attribute you can specify
				<emphasis role="bold">classpath</emphasis>
				datasets location. Locations
				are relative to test class location.
				Note that more than one dataset
				can
				be specified. 
			</para>
			<para>
			Also <methodname>withSelectiveLocations</methodname> attribute can be used to specify datasets location. See <link linkend="advanced.simultaneous-engine-title">Advanced Usage</link> chapter for more information.
			</para>
			<para>
				If files are not
				specified explicitly, next strategy is
				applied:
			</para>

			<itemizedlist>
				<listitem>
					<para>
						First searches for a file on classpath in same package of test
						class with next file name,
						<filename>[test class name]#[test method
							name].[format]
						</filename>
						(only if annotation is present at test
						method).
					</para>
				</listitem>

				<listitem>
					<para>
						If first rule is not met or annotation is defined at class
						scope,
						next file is searched on classpath in same package of test
						class,
						<filename>[test class name].[default format]</filename>
						.
					</para>
				</listitem>
			</itemizedlist>

			<warning>
				<para>
					datasets must reside into
					<emphasis>classpath</emphasis>
					and
					format depends on
					<emphasis>NoSQL</emphasis>
					vendor.
				</para>
			</warning>

			<para>Second attribute provides strategies for inserting data.
				Implemented strategies are:
			</para>

			<table border="1">
				<caption>Load Strategies</caption>

				<tr>
					<td>INSERT</td>

					<td>Insert defined datasets before executing any test method.</td>
				</tr>

				<tr>
					<td>DELETE_ALL</td>

					<td>Deletes all elements of database before executing any test
						method.
					</td>
				</tr>

				<tr>
					<td>CLEAN_INSERT</td>

					<td>This is the most used strategy. It deletes all elements of
						database and then insert defined datasets before executing any
						test
						method.
					</td>
				</tr>
			</table>

			<para>An example of usage:</para>

			<programlisting language="java"><![CDATA[@UsingDataSet(locations="my_data_set.json", loadStrategy=LoadStrategyEnum.INSERT)]]></programlisting>
		</section>

		<section>
			<title xml:id="verifying_database">Verifying Database</title>

			<para>
				Sometimes it might imply a huge amount of work asserting database
				state directly from testing code. By using
				<emphasis>@ShouldMatchDataSet</emphasis>
				on test method,
				<emphasis role="bold">NoSQLUnit</emphasis>
				will check if database contains
				expected entries after test
				execution. As with
				<emphasis>@ShouldMatchDataSet</emphasis>
				annotation you can define
				classpath file location, or using <methodname>withSelectiveMatcher</methodname> See <link linkend="advanced.simultaneous-engine-title">Advanced Usage</link> chapter for more information. 
			</para>

			<para>
			If it is not dataset is supplied next convention is	used:
			</para>

			<itemizedlist>
				<listitem>
					<para>
						First searches for a file on classpath in same package of test
						class with next file name,
						<filename>[test class name]#[test method
							name]-expected.[format]
						</filename>
						(only if annotation is present at
						test method).
					</para>
				</listitem>

				<listitem>
					<para>
						If first rule is not met or annotation is defined at class
						scope,
						file is searched on classpath in same package of test class,
						<filename>[test class name]-expected.[default format]</filename>
						.
					</para>
				</listitem>
			</itemizedlist>

			<warning>
				<para>
					datasets must reside into
					<emphasis>classpath</emphasis>
					and
					format depends on
					<emphasis>NoSQL</emphasis>
					vendor.
				</para>
			</warning>

			<para>An example of usage:</para>

			<programlisting language="java"><![CDATA[@ShouldMatchDataSet(location="my_expected_data_set.json")]]></programlisting>
		</section>
	</section>

</chapter>




© 2015 - 2025 Weber Informatics LLC | Privacy Policy