57
Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: – Client: – often uses a web browser, but could also be an client application – sends requests for web pages – receives response – Database: – stores persistent data such as item catalogues, transaction records, etc. Application server – receives requests and constructs a web page response – handles access control, session management, etc. Client Application server Database

Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Embed Size (px)

Citation preview

Page 1: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Testing Web-based applications

• Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts:– Client:

– often uses a web browser, but could also be an client application

– sends requests for web pages– receives response

– Database: – stores persistent data such as item

catalogues, transaction records, etc.– Application server

– receives requests and constructs a web page response

– handles access control, session management, etc.

Client

Applicationserver

Database

Page 2: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

The Client layer

• Web pages are represented by HTML, the HyperText Markup Language.

• The protocol to send and receive web pages from a web server is HTTP, the HyperText Transfer Protocol.

• What’s useful to know about HTTP in this context?

– It was intended as a request – response protocol without any state.

– It is entirely text-based and (somewhat) human-readable.

Page 3: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Application Servers

• Typical functions:

– Management of concurrent sessions and transactions

– Construction of dynamic and static web pages

– Arrange for storage and retrieval of persistent data

– Handling of business logic

– Security

Page 4: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

The Database interface

• The connection to a database via a programming language is via a connection protocol API (application programming interface):

– ODBC: open database connectivity

– JDBC: specific version for Java

– Since databases are not compatible, there are normally specific drivers loaded in for each type of database (Oracle, MySQL, etc.)

– Specify a URL such as jdbc:mysql://ste5007.site.uottawa.ca:3306/db to connect, and then provide a userid and password.

• After logging in, SQL (structured query language) commands are issued to insert, view, update, or delete data.

• Results from the database are loaded into a O/JDBC object for use.

Page 5: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

For this presentation:

• Some assumptions on the environment for the purposes of this presentation:

– Code is based on the Java Enterprise Edition (EE) software development kit, version 1.4 or earlier (i.e. not Java EE 5)

– Use of a web application server that conforms to the Java EE specification

Page 6: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Java Application Servers

• Java EE servers use the concept of a “container” in which processing of a session is handled.

• Java classes are deployed into a container, and then interact with the container to provide functionality for the server.

• The container manages the creation and life cycle of the objects deployed within, and access to these objects.

Page 7: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Java Application Servers

Container

HTTPresponse,containingHTML

HTTPrequest

DB

Application server

Client /Browser

EnterpriseJavaBean(EJB)

JavaServerPage(JSP)

ServletFilter

TagLibrary

Page 8: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Server options

• Production-capable server:

– Apache Tomcat, Sun JAS, Glassfish (for EE 5), JBoss, BEA, IBM WebSphere, Oracle Application Server, JOnAS, ...

• Simplified server:

– Jetty

• No server:

– Mock object generator that provides mocks for the HTTP interface or the DB interface.

Page 9: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Testing the client

• If the purpose of testing is to test behaviour at the client, then various approaches are possible.

– Use an actual production-capable application server (including possibly even the database layer).

– Use an application server (perhaps a with stubs for web pages

– Web pages are empty or nearly so, with no dynamic content.

– Replace the application server with a stub or mock object that works with the HTTP protocol. The mock connection is the interface to the client.

– Test client objects directly with JUnit.

Page 10: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Testing the client

HTTPresponse,containingHTML

HTTPrequest

Client /Browser

EmbeddedApplication

Server

JUnitTestCase

Page 11: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Testing the client

HTTPresponse,containingHTML

HTTPrequest

Client /Browser

MockConnection

JUnitTestCase

Page 12: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

HTTP primary commands

• GET: request a resource

GET /~awilliam/csi5118 HTTP/1.1Host: www.site.uottawa.ca

• POST: submit data for processing

POST /index.html HTTP/1.1Host: www.example.com...Content-type: application/x-www-form-urlencoded...searchword=findme&option=search&submit=go

File to retrieve

Form data

File from whichdata was posted

Page 13: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

HTTP responses

• HTTP returns a numeric 3-digit code, header information, plus content.

• Frequent codes:– 200 OK: request was satisfied, and message

contains content.

HTTP/1.1 200 OK...Content-length: 43794Content-type: text/html...<html>...</html>

– 404 Not found: the resource requested could not be located.

Success

Web page in HTML

Contentinformation

Page 14: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Potential test purposesat the Client Interface

• Check that when a user action occurs, the correct data is put into an HTTP request

– Link has correct uniform resource locator (URL) address.

– Data in POST command is as expected, and formatted correctly.

• Check that when an HTTP request is sent to the server, the response is as expected.

– HTTP response is correct

– HTML response is correct– Search for particular items within a web page to see if

they are included (especially for dynamically generated pages)

– Correct page– Correct page elements (buttons, etc.)– Data is as expected.

Page 15: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Sample: Web client that returnsa string read from a web server

public class WebClient{ public String getContent( URL url ) { StringBuffer content = new StringBuffer(); try { HttpURLConnection connection = (HttpURLConnection) url.openConnection( ); connection.setDoInput( true ); InputStream is = connection.getInputStream( ); byte[] buffer = new byte[2048]; int count; while ( -1 != ( count = is.read( buffer ) ) ) { content.append( new String( buffer, 0, count ) ); } } catch ( IOException e ) return null; return content.toString( ); }}

Page 16: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Client test strategies

• To test this client, we have to arrange for some known data to appear from the URL, and be sure that the client reads it correctly.

• Two approaches:

– Use an embedded server that we can control.

– Use a stub or mock object for the connection.

Page 17: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Test strategy 1: Embedded server

HTTPresponse,containingHTML

HTTPrequest

Client /Browser

EmbeddedApplication

Server

JUnitTestCase

Page 18: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Jetty

• Jetty is a small application server that can be embedded within a Java application.

– http://www.mortbay.org/

• For running JUnit, Jetty can be started within the same virtual machine.

• Jetty can be provided with various “contexts” and handlers

– Essentially, a context defines a relative URL for which the Jetty server will accept requests.

– Handlers tell Jetty how to construct responses.

Page 19: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Setup for Embedded Jetty Server

public class WebClientTest{ private static HttpServer server; @BeforeClass public static void setUpBeforeClass( ) throws Exception { server = new HttpServer(); SocketListener listener = new SocketListener(); listener.setPort( 8080 ); server.addListener( listener ); HttpContext context1 = new HttpContext(); context1.setContextPath( "/testGetContentOK" ); context1.addHandler( new TestGetContentOKHandler() ); server.addContext( context1 ); HttpContext context2 = new HttpContext(); context2.setContextPath( "/testGetContentNotFound" ); context2.addHandler( new NotFoundHandler() ); server.addContext( context2 );

server.start( );} URL for the context will be

http:localhost:8080/testGetContentOK

Handler for requests

Page 20: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Jetty Handlers

public class TestGetContentOKHandler extends AbstractHttpHandler

{

public void handle( String pathInContext, String pathParams,

HttpRequest theRequest, HttpResponse theResponse )

throws HttpException, IOException

{

OutputStream out = theResponse.getOutputStream( );

ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer( );

writer.write( "It works" );

writer.flush( );

theResponse.setIntField( HttpFields.__ContentLength,

writer.size( ) );

writer.writeTo( out );

out.flush( );

theRequest.setHandled( true );

}

}

Page 21: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Sample test + Teardown

@Testpublic void testGetContentOK( ) throws MalformedURLException{ WebClient client = new WebClient( ); URL url = new URL("http://localhost:8080/testGetContentOK"); String expected = "It works"; String actual = client.getContent( url ); assertEquals( expected, actual );}

@AfterClasspublic static void tearDownAfterClass( ) throws Exception{ server.stop();}

Page 22: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Strategy 2: No server

HTTPresponse,containingHTML

HTTPrequest

Client /Browser

StubConnection

JUnitTestCase

Page 23: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Strategy 2: Implementation

HTTPresponse,containingHTML

HTTPrequest

Client /Browser

StubURL

StreamHandler

JUnitTestCase

URL

StubStreamHandlerFactory

StubURL

Connection

Page 24: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Stub for the URL connection

public class StubHttpURLConnection extends HttpURLConnection{ private boolean isInput = true; protected StubHttpURLConnection( URL url ) { super( url ); } public InputStream getInputStream( ) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream( new String( "It works" ) .getBytes( ) ); return bais;}

Page 25: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Sample test + Setup

@BeforeClasspublic static void setUpBeforeClass( ) throws Exception{ URL.setURLStreamHandlerFactory( new StubStreamHandlerFactory() );}

@Testpublic void testGetContentOK( ) throws MalformedURLException{ WebClient client = new WebClient( ); URL url = new URL("http://localhost:8080/testGetContentOK"); String expected = "It works"; String actual = client.getContent( url ); assertEquals( expected, actual );}

Page 26: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Testing Application Server Classes

• In-container approach:– This is the actual environment in which the class

would be run.– Requires deploying classes to an application server

(complex, time-consuming setup)– Access to classes for test purposes is restricted by

the container.

• Out-of-container approach:– Requires stubs or mock objects for interactions with

the container.– Not the actual running environment.– Once the container environment is simulated, tests

can be run quickly.

Page 27: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Java Application Servers (reprise)

Container

HTTPresponse,containingHTML

HTTPrequest

DB

Application server

Client /Browser

EnterpriseJavaBean(EJB)

JavaServerPage(JSP)

ServletFilter

TagLibrary

Page 28: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Servlets

• Servlets are a mechanism for an application server to construct dynamic web page content.

• Example:– User enters a value into a text field on a web page

and clicks a “submit” button.– An HTTP command is constructed by the browser

and sent to the server.– The application server will parse the HTTP command,

determine which session the command belongs to, and construct an HttpServletRequest object containing the request information.

– The servlet’s function is to create an HttpServletResponse object that contains information needed to create the HTTP reply that contains the HTML to be displayed in the user’s browser.

Page 29: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

The Servlet Environment

Container

Servlet

HttpServletResponse

HTTPresponse,containingHTML

HttpServletRequest

HTTPrequest

DB

Application server

Browser

Page 30: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

A (small) Sample Servlet

• Purpose: As part of handling a request, this method checks to see if the session associated with the request has stored a attribute indicating that the session was authenticated.

public class SampleServlet extends HttpServlet implements Servlet{ public boolean isAuthenticated( HttpServletRequest request ) { HttpSession session = request.getSession( false ); if ( session == null ) { return false; } String authenticationAttribute = ( String ) session

.getAttribute( "authenticated" ); return Boolean.parseBoolean( authenticationAttribute ); }}

Page 31: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

How to test the Servlet?

• Because this method asks for the container’s session parameters, direct JUnit test cases are not possible in this environment.

– The HttpServletRequest object is created by the container and is only available there. The request also must return a valid HttpSession to check the attribute.

• To test this code without the container, mock objects for the HttpServletRequest and HttpSession objects are needed.

Page 32: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Servlet Testing approaches

• Three ways of running test cases for this servlet will be shown here.

1. Out of container, using mock objects created by EasyMock.

2. In container, using the Apache Tomcat server and Cactus

3. In container, using the embeddable Jetty server and Cactus.

Page 33: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Out-of-container Strategy

Servlet

HttpServletResponse

HttpServletRequest

MockDB

JUnitTestCase

Page 34: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

The sample servlet, again

public class SampleServlet extends HttpServlet implements Servlet{ public boolean isAuthenticated( HttpServletRequest request ) { HttpSession session = request.getSession( false ); if ( session == null ) { return false; } String authenticationAttribute = ( String ) session

.getAttribute( "authenticated" ); return Boolean.parseBoolean( authenticationAttribute ); }}

Page 35: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Mock objects test case – setup and teardown

public class MockObjectTest{ private SampleServlet servlet; private HttpServletRequest theRequest; private HttpSession theSession;

@Before public void setUp( ) throws Exception { servlet = new SampleServlet( ); theRequest = EasyMock.createMock(HttpServletRequest.class ); theSession = EasyMock.createMock( HttpSession.class ); }

@After public void tearDown( ) throws Exception { EasyMock.verify( theRequest ); EasyMock.verify( theSession ); }

Page 36: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Mock object test case –test method

@Testpublic void testIsAuthenticatedTrue( ){ EasyMock.expect( theRequest.getSession( false ) ) .andReturn( theSession ); EasyMock.expect( theSession.getAttribute("authenticated") ) .andReturn("true"); EasyMock.replay( theRequest ); EasyMock.replay( theSession );

boolean expected = true; boolean actual = servlet.isAuthenticated( theRequest ); Assert.assertEquals( expected, actual );}

Page 37: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Running the test case

• All the previous test case needs to run is to ensure the EasyMock class library is available.

• Tests are run without using an application server, and are run directly by JUnit.

• Advantages:

– Test is easy to set up and will run quickly

• Disadvantages:

– The test is not running in the actual servlet container, and we don’t know if the container will provide the correct request or not.

Page 38: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

In-container Strategy (1)

Container

Servlet

Response

Request

TestDB

Application server

JUnitTestCase

Page 39: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

In-container Strategy (2)

Container

Servlet

Response

Request

TestDB

Application server

JUnitTestCase

JUnitTest

Proxy

Page 40: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

In-container testing with Cactus

• Cactus: part of the Apache Jakarta project

– jakarta.apache.org/cactus

• Cactus is a framework to install a test component inside an application server, and to communicate with that test component.

– Extension of the JUnit framework

• Result: You can run JUnit tests from outside the container, but have the tests executed inside the container.

Page 41: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

How Cactus Works

• Cactus uses a proxy mechanism to run test cases at the client, and redirect the requests to a copy of the test case inside the server container.

Page 42: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

In-container testing with Cactus

• What is required:

1. Include the JUnit and Cactus libraries as part of the deployment to the application server container.

2. Implement a client redirector that takes a JUnit test case run outside the container, and duplicate it within the container.

3. Implement a server redirector that lets Cactus intercept incoming requests during test case execution and provide them as objects to the test case.

4. Provide a mechanism to get the test case results back from the container to the test runner.

Page 43: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Cactus JUnit test cases

• Test class must inherit from one of the following classes:

– org.apache.cactus.ServletTestCase, to test a servlet

– org.apache.cactus.FilterTestCase, to test a filter

– org.apache.cactus.JspTestCase, to test a Java server page

Page 44: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Cactus JUnit test cases

• For a servlet test case, the JUnit test case will have access to the following objects:

– request

– response

– config

– session

• The servlet context can also be accessed indirectly.

Page 45: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Structure of a Cactus test

• begin(), end(): executed on the client side before and after each test case

• setUp(), tearDown(): executed on the server side before and after each test case

• testXXX(): a test method, to be executed within the server container

• beginXXX(WebRequest request): a method to be executed on the client immediately before testXXX().– The parameter is used to set up the request to be

passed to the server.

• endXXX(WebResponse theResponse ): a method to be executed at the client immediately after testXXX(). This is used to verify the HTTP response from the user.

Page 46: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

How Cactus Works

• Here is the order of execution of the various methods:

Page 47: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

First In-Container Test Project

• Goal: Execute a servlet test case on an Apache Tomcat application server.

• Create an Eclipse “dynamic web” project

– The target server is defined at project creation time.

– Eclipse will create the web.xml deployment descriptor for the project.

– Using the servlet wizard to create the servlet will add the servlet to the deployment descriptor

Page 48: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Additions to Deployment Descriptor

• Cactus redirectors must be added to the web.xml file, so that they can be part of the project deployment.

<servlet> <servlet-name>ServletRedirector</servlet-name> <servlet-class> org.apache.cactus.server.ServletTestRedirector </servlet-class></servlet>

<servlet-mapping> <servlet-name>ServletRedirector</servlet-name> <url-pattern>/ServletRedirector</url-pattern></servlet-mapping>

Page 49: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Test class, part 1

public class TomcatCactusTest extends ServletTestCase{

private SampleServlet servlet;

@Beforepublic void setUp( ) throws Exception{

servlet = new SampleServlet( );}

@Testpublic void testIsAuthenticatedTrue( ){

session.setAttribute( "authenticated", "true" );boolean actual =

servlet.isAuthenticated( request );boolean expected = true;assertEquals( expected, actual );

}

Page 50: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Test class, part 2

@Testpublic void testIsAuthenticatedFalse( ){

boolean actual = servlet.isAuthenticated( request );boolean expected = false;assertEquals( expected, actual );

}

public void beginIsAuthenticatedNoSession( WebRequest theRequest )

{theRequest.setAutomaticSession( false );

}

@Testpublic void testIsAuthenticatedNoSession( ){

boolean actual = servlet.isAuthenticated( request );boolean expected = false;assertEquals( expected, actual );

}

Page 51: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Eclipse view of projectwith Cactus deployment descriptor

Page 52: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Libraries needed

• For the client:– junit.jar [from JUnit]– servlet-api.jar [from target Application Server]– cactus.jar– aspectjrt.jar– commons-httpclient.jar– commons-logging.jar

• For the server:– junit.jar [from JUnit]– Application server libraries– cactus.jar– aspectjrt.jar– commons-logging.jar

Page 53: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Libraries added to Eclipse projectfor Cactus

Page 54: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Test run on Tomcat Server

Page 55: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Cactus + Jetty

• Cactus is used to run test cases inside the container provided by Jetty.

• Jetty can run the previous servlet test case that was run on the Tomcat server.

• Since Jetty is embedded, the server will be started by the test case.

– Cactus provides a wrapper to set up tests within Jetty by doing a combined server start-up and test case deployment.

Page 56: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Cactus test wrapped for Jetty

// The @RunWith line is needed for JUnit 4 to run test suite

@RunWith( AllTests.class ) public class JettyCactusTest{

public static Test suite( ){

// The next line adapts a JUnit 4 test for a JUnit 3 runner Test suite3 = new JUnit4TestAdapter( TomcatCactusTest.class ); System.setProperty( "cactus.contextURL", "http://localhost:8080/test" ); TestSuite suite = new TestSuite( "All tests with Jetty" ); suite.addTest( suite3 ); return new JettyTestSetup( suite );

}}

Page 57: Testing Web-based applications Typically, a multi-layered architecture is used. Three primary layers, typically on different hosts: –Client: –often uses

Test run on embedded Jetty server