Das [ServletUnitProtocol] ist ein Protocol zur Integration der [HttpUnit|http://en.wikipedia.org/wiki/HttpUnit]. [ServletUnitProtocol] ist Bestandteil von [Intersult Testing] und für die [ProtocolFactory] geeignet. Falls eine Browser-Simulation eingesetzt werden soll, kann [HtmlClient] verwendet werden.

!!!Anwendung
[ServletUnitProtocol] ist zunächst ein Protocol, das durch einen einfachen Aufruf mit der [ProtocolFactory] aktiviert wird.

Damit können WAR-Projekte direkt getestet werden, ohne über das TCP/IP-System zu gehen. Es wird eine direkte Stream-Verbindung (java.io) zwischen dem Aufrufer und dem Servlet hergestellt. Die Server-Komponenten können dabei direkt über die web.xml definiert werden, sodass ein WAR-Projekt direkt aufgerufen werden kann.

Das [ServletUnitProtocol] kann für die Konfiguration von anderen Komponenten wie [Abraxas] verwendet werden.

!!!Konfiguration
Das [ServletUnitProtocol] unterstützt einige Parameter zur Konfiguration:

||Parameter||Bedeutung
|webXmlFile|Der Pfad an dem sich die web.xml-Datei befindet, Standard ist "src/main/webapp/WEB-INF/web.xml"
|contextPath|Der Kontext-Pfad der laufenden Web-Anwendung, also http://localhost/<contextPath>/..." Standard ist "/".
|translateProtocol|Standard ist, dass die Web-Anwendung im Aufruf-URL als Protocol einen URL mit "unit://localhost/..." übergeben bekommt. Meist ist dies nützlich, da die Links auf Web-Seiten so auch wieder auf das Protocol verweisen. Einige Anwendungen können damit Probleme haben, daher kann dieses Verhalten durch den Wert false abgeschaltet werden. In diesem Fall wird die URL zu "http://localhost/..." übersetzt.

!!!Beispiele
!Echo-Servlet
{{{
	String message = "Hello World!";
	URL url = new URL("unit://localhost/echo");
	HttpUnitConnection connection = (HttpUnitConnection)url.openConnection();
	connection.setDoOutput(true);
	connection.addRequestProperty("Content-Type", "text/plain");
	IOUtils.write(connection.getOutputStream(), message);
	String response = IOUtils.readString(connection.getInputStream());
	Assert.assertEquals(message, response);
}}}

Und in der web.xml:

{{{
    <servlet>
        <servlet-name>EchoServlet</servlet-name>
        <servlet-class>com.intersult.testing.EchoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    	<servlet-name>EchoServlet</servlet-name>
    	<url-pattern>/echo</url-pattern>
    </servlet-mapping>
}}}

!Integrations-Test
Das [ServletUnitProtocol] kann auch als Integrationstest eingesetzt werden, also nicht auf dem Quellverzeichnis /src/main/webapp/ sondern unter /target/<name>/. Dies ist sinnvoll, wenn Ressourcen gefiltert oder generiert werden.

Zunächst wird das Output-Directory in das Build-Verzeichnis gelegt, sodass das exploded WAR-Verzeichnis komplett ist:

{{{
<build>
	<finalName>name</finalName>
	<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
	...
</build>
}}}

Der Test kann dann so aussehen:

{{{
public class ITCheck {
	@BeforeClass
	public static void beforeClass() {
		HttpUnitProtocol protocol = new HttpUnitProtocol("/name");
		protocol.setWebXmlFile("target/name/WEB-INF/web.xml");
		ProtocolFactory.register(protocol);
	}
	
	@Test
	public void test() throws Exception {
		HtmlClient client = new HtmlClient(new UrlClient());
		URL url = new URL("unit://localhost/");
		Page page = client.begin(url, null, false);
		Element error = page.getElement("/HTML/BODY/H2[1]");
		Assert.assertNull(error);
	}
}
}}}

__Erklärung:__ Die statische Methode beforeClass registriert das [ServletUnitProtocol]. Die Methode test erzeugt einen neuen HtmlClient, der einen GET-Request auf die URL unit://localhost/ absetzt. Die erzeugte HTML-Seite wird geparsed und als Page-Objekt zurückgegeben. Danach wird getestet, dass sich auf der Seite kein Element mit dem Xpath "/HTML/BODY/H2[1]" befindet.

!!!Application-Server
[HttpUnit|http://en.wikipedia.org/wiki/HttpUnit] stellt eine leichtgewichtige Implementierung der Servlet-API dar. Die Implementierung umfasst Servlets, Servlet-Filter, Sessions und weitere Teile. Daher können die meisten Anwendungen getestet werden, die auf einer web.xml basieren (als WAR gepackt werden).

!!!Java Server Pages (JSP)
HttpUnit alle wesentlichen Bestandteile, um JSPs zu verwenden. Dazu sind die folgenden Artifakte hinzuzufügen:

!JSP mit Tomcat 5
{{{
	<dependency>
		<groupId>tomcat</groupId>
		<artifactId>jasper</artifactId>
		<version>3.3.2</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>tomcat</groupId>
		<artifactId>jasper-compiler</artifactId>
		<version>5.5.23</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>tomcat</groupId>
		<artifactId>tomcat-util</artifactId>
		<version>5.5.23</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>tomcat</groupId>
		<artifactId>core_util</artifactId>
		<version>3.3.2</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>com.sun</groupId>
		<artifactId>tools</artifactId>
		<version>1.4.2</version>
		<scope>system</scope>
		<systemPath>${java.home}/../lib/tools.jar</systemPath>
	</dependency>
}}}

__Erklärung:__ Jasper ist eine Compilier-Einheit für JSPs, die unter anderem in Tomcat verwendet wird. Zusätzlich wird tools.jar aus der bestehenden Java-Installation hinzugefügt, weil Jasper den Java-Compiler nutzt.

!JSP mit Tomcat 7
Bei Tomcat 7 ist die Konfiguration anders, weil er die Embedded Libraries mitbringt, eine eigene JSP-API und den Eclipse-JDT-Compiler verwendet:

{{{
		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-jsp-api</artifactId>
			<version>${tomcat-version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-core</artifactId>
			<version>${tomcat-version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-logging-juli</artifactId>
			<version>${tomcat-version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-logging-log4j</artifactId>
			<version>${tomcat-version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<version>${tomcat-version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.eclipse.jdt.core.compiler</groupId>
			<artifactId>ecj</artifactId>
			<version>3.7</version>
			<scope>test</scope>
		</dependency>
}}}

Dazu kommt der Tomcat-Instance-Manager, der gewöhnlich beim Starten des Tomcat erzeugt wird. Da durch [ServletUnitProtocol] kein Tomcat gestartet wird, injeziert man den InstanceManager selbst in den Servlet-Context:

{{{
	StandardContext context = new StandardContext();
	context.setLoader(new WebappLoader(Thread.currentThread().getContextClassLoader()));
	Map<String, Map<String, String>> injectionMap = new HashMap<String, Map<String,String>>();
	InstanceManager instanceManager = new DefaultInstanceManager(null, injectionMap, context, Thread.currentThread().getContextClassLoader());
	HttpUnitProtocol protocol = new HttpUnitProtocol("/test");
	protocol.getRunner().setContextParameter(InstanceManager.class.getName(), instanceManager);
}}}

!HttpUnit und HtmlClient
[HttpUnit|http://en.wikipedia.org/wiki/HttpUnit] ist eine Software zur Simulation eines Servlet-Container. Zusätzlich enthält HttpUnit weitere Teile zur Simulation eines Browsers, die von [ServletUnitProtocol] nicht verwendet werden. Mit der URLConnection ist die Simulation eines Servlet-Containers abgeschlossen.

Die Simulation eines Browsers kann dann mit einem [HtmlClient] erfolgen, der systemkonform über die URLConnection geht. Dadurch sind Server- und Client völlig entkoppelt, können daher beliebig simuliert und getestet werden.

!!!Fragen & Antworten (Q&A)
!InstanceManager
__Frage:__ Die Fehlermeldung: 500 org.apache.jasper.JasperException: java.lang.IllegalStateException: No org.apache.tomcat.InstanceManager set in ServletContext

__Antwort:__ Es sind folgende [Bibliotheken|http://www.intersult.com/wiki/Wiki.jsp?page=HttpUnitProtocol#section-HttpUnitProtocol-JavaServerPagesJSP] einzubinden.