java.io.StreamCorruptedException: InputStream does not contain a
serialized object
error. What does it mean?not a valid response
error message. What does it
mean? ChainedRuntimeException
: Failed to get the test results"
error message. What does it mean? If you get the following stack trace:
java.lang.ExceptionInInitializerError: java.util.MissingResourceException: Can't find bundle for base name cactus, locale en_GB at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:707) at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:679) at java.util.ResourceBundle.getBundle(ResourceBundle.java:546)
it simply means that you have not put the cactus.properties file in your CLASSPATH (i.e. the directory which contains this file should be in the CLASSPATH). This file is the Cactus configuration file and is required. Check the Cactus Configuration Howto page for more information.
[top] |
Cactus needs to have a few entries set in the web.xml
file (redirector definition and mappings mostly). The application to
test also needs its own entries. What would be nice would be to be
able to use the same web.xml
file in the build process
for both application testing and deployment to production.
Here's how I accomplished conditional inclusion of Cactus web.xml configuration. My web.xml file is capable of working standalone without requiring any filtered copy to work. In Ant I'm doing this:
<copy todir="${admin.build.dir}/WEB-INF" file="web/admin/WEB-INF/web.xml" overwrite="yes"> <filterset> <filter token="start.cactus.config" value="-->"></filter> <filter token="end.cactus.config" value="<!--"></filter> </filterset> </copy>
In web.xml
I have this:
<![CDATA[ <!-- Cactus configuration Note: Do not place any XML comments in this Cactus configuration section (Ant's filtered copy is used to activate this configuration when the test web application is built) --> <!-- Begin Cactus Configuration @start.cactus.config@ <servlet> <servlet-name>ServletRedirector</servlet-name> <servlet-class>org.apache.cactus.server.ServletTestRedirector</servlet-class> </servlet> <servlet> <servlet-name>JspRedirector</servlet-name> <jsp-file>/somewhere/jspRedirector.jsp</jsp-file> </servlet> <servlet-mapping> <servlet-name>ServletRedirector</servlet-name> <url-pattern>/ServletRedirector/</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>JspRedirector</servlet-name> <url-pattern>/JspRedirector/</url-pattern> </servlet-mapping> @end.cactus.config@ End Cactus Configuration --> ]]>
[top] |
java.io.StreamCorruptedException: InputStream does not contain a
serialized object
error. What does it mean?This exception results when client-side Cactus code attempts to talk to a misconfigured installation of Cactus on the server side. The reason for the obscure exception is this: Cactus makes two requests to the server. In the first, the client-side test runner requests that such-and-such a test be run on the server (an oversimplification, please see: XXXX). Immediately after the response from the server the client code makes a second request, this time for the results of the server-side test. Cactus is supposed to send back a serialized Object containing the results. Cactus then attempts to deserialize this Object from the input stream in the response. If Cactus is installed properly on the server, this process works transparently. If not (for instance the second request does not even arrive at a Cactus redirector) then the response to the second request (which very well may be a 404 or 500 error) will not contain the object that client-cactus expects. This leads to the StreamCorruptedException.
When troubleshooting this error, the most likely prospect
is that the requests from client-Cactus are not even
reaching server-Cactus. This can happen when the
cactus.properties
contains a bad entry. For instance, I
have run into this problem when building several different
testing-applications. I tried to run my tests against
http://localhost/webapp1/ServletRedirector/
when I needed
to be running against
http://localhost/webapp2/ServletRedirector/
. This can
also happen if your web.xml file contains an error, or does not
properly map the URLs contained in cactus.properties to the
Cactus redirectors.
A good way to check whether your requests are reaching a
Cactus redirector is to manually enter in the URLs for all
of the redirectors you use into the navigation bar of your
web-browser. Actually the Cactus redirectors provide a URL just for
that: http://localhost/webapp/ServletRedirector?Cactus_Service=RUN_TEST
(this also works for the other redirectors).
http://localhost/webapp/ServletRedirector
directly, you'll get a 500 error and get a stack trace (in the log or
along with your error page) that says
. This is because the
Cactus redirector expects HTTP parameter from the Cactus client side.
Another likely error is that your server-side classpath
does not contain a copy of the cactus.jar. (Cactus is
effectively not present on the server.) According to
e-mails on the Cactus user list, the
StreamCorruptedException
could also result when you are
using the wrong version of the servlet.jar in some area
(any version prior to 2.2, or using servlet.jar 2.2 with a
Cactus-1.3 installation).
[top] |
Let's imagine that I have one servlet that performs an HTTP redirect to a JSP page (or to another servlet). How do I test it with Cactus?
Short answer: you don't !
Long answer: Cactus is meant to be a unit testing tool, meaning it lets you perform tests for a given method and then it lets you assert the result from that method.
In the above scenario, a typical Cactus test will consist in
verifying that the return HTTP response is an HTTP redirect (by
checking the HTTP response code - 302 - in the endXXX()
method) and possibly also checking the URL of the redirect page.
Then, as a second test, you could (if you wish) verify that calling
the URL of the JSP does return such HTML content (using HttpUnit
integration for example). Note that this second test is rather a
functional test than a unit test but it can still be viewed as
unit testing the doGet()
method of the JSP ...
[top] |
When I use the runservertests
Cactus custom Ant
task, it starts my server allright but then hangs and the tests are
not executed. What is happening?
It means that the testURL
attribute you've specified
in runservertests
is not a valid URL. It must
be a URL that is valid when the server is up. To diagnosis the
problem simply open a browser once your server is started (i.e. when
the task hangs) and type the URL in your browser. An alternative to
debug is also to run Ant in debug mode
(ant -debug [your target]
).
With Cactus 1.3, the correct URL to call is the following, which is
always valid:
http://localhost:8080/webapp/ServletRedirector?Cactus_Service=RUN_TEST
.
Of course replace webapp
by your webapp context and
replace the port by the one you're using.
[top] |
not a valid response
error message. What does it
mean? When I run my Cactus test, I'm getting the following:
testRequestDispatcherInclude(org.apache.cactus.sample.TestSampleServlet) org.apache.cactus.util.ChainedRuntimeException: Not a valid response at org.apache.cactus.client.WebTestResultParser.readRootElement( WebTestResultParser.java;org/apache/cactus/util/log/LogAspect.java(1k):134)
It means that Cactus could not connect to the server side properly. There could several reasons for this: a valid Redirector URL but not pointing to the Redirector, a secured resource, etc.
To easiest way to diagnosis the problem is to enable Cactus logging
(see the Configuration Howto
for how to do this). The cactus client log
(cactus_client.log
will clearly give the error).
[top] |
ChainedRuntimeException
: Failed to get the test results"
error message. What does it mean? When I run my Cactus test, I'm getting the following:
org.apache.cactus.util.ChainedRuntimeException: Failed to get the test results [...]
It means that Cactus failed to retrieve the test result from the
server side for some reason. To easiest way to diagnosis the problem
is to enable Cactus logging(see the
Configuration Howto
or how to do this). The cactus client log
(cactus_client.log
will clearly give the error).
[top] |
How to send multipart/form-data to my servlet under test?
Use a recent version of Commons-httpclient, which supports sending multipart data. Tobias also has a nice blog entry describing how to use Java NIO, Commons-httpclient and Cactus to upload a file.
Another solution is to use the HTTPClient classes from Ronald Tschalar, as demonstrated in the following example:
import HTTPClient.Codecs; import HTTPClient.NVPair; . . . NVPair[] hdrs = new NVPair[1]; public void beginUpload(WebRequest theRequest) { NVPair[] opts = { new NVPair("option", "myoption") }; NVPair[] file = { new NVPair("comment", "/home/alan/src.zip") }; try { byte[] data = Codecs.mpFormDataEncode(opts, file, hdrs); InputStream i = new ByteArrayInputStream(data); theRequest.setUserData(i); theRequest.setContentType(hdrs[0].getValue()); i.close(); } catch (IOException e) { System.out.println("Error Building Multipart"); } }
[top] |
Cactus tests run fine when I use the JUnit TextTestRunner but fails with other runners like the SwingTestRunner. I get the following exception:
org.apache.commons.logging.LogConfigurationException: java.lang.ClassCastException: org.apache.commons.logging.impl.LogFactoryImpl at org.apache.commons.logging.LogFactory.newFactory(LogFactory.java:505) at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:340) at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:381) at org.apache.cactus.AbstractTestCase.runBare(AbstractTestCase.java:188)
Check the
excluded.properties
file (see the JUnit FAQ).
[top] |
I would like to pass some configuration information to my Cactus tests but without having to hardcode them in my tests. Can I do this, and how?
The easiest solution is to pass dynamic configuration information as System properties to Cactus. For example, if you have to pass a username and password as HTTP parameter to your servletfor all your tests and you cannot control your environment by defining a test user, you could write the following:
public void MyTest extends ServletTestCase { public void begin(WebRequest request) { request.addParameter("username", System.getProperty("username")); request.addParameter("password", System.getProperty("password")); } [...] }
In order to pass the system properties to cactus you have 2 options:
cactus.properties
file.
All properties found in this file are imported as System
Properties during the Cactus initialization.
[top] |
I would like to use the same HTTP Session between several Cactus tests. How can I do that?
Cactus is a unit testing framework and not a functional testing
framework. Each test must be independent of the others.
There are several reasons for this: tests become very brittle,
test order is not guaranteed by the JVM, etc. Thus, before each
test you must set the fixture. This can be factorized in the
setUp()
method or in the Cactus begin()
method.
[top] |
The Cactus plugin for Eclipse requires Eclipse 2.1 RC2 or greater. It has not yet been tested with Eclipse 3.0.
[top] |
When running my Cactus tests with JBoss 3.x, I get:
java.lang.NoSuchMethodError: org.apache.commons.httpclient.methods.GetMethod.setRequestHeader( Ljava/lang/String;Ljava/lang/String;)V at [...]
JBoss 3.x bundles an old version of HttpClient and Cactus requires a newer version. Just replace the HttpClient version in JBoss by the one provided by Cactus.
[top] |
Answer: No. For each test, Cactus performs 2 HTTP connections to the Server side: one for executing the test and one to get the test result. The test result is stored in the application scope (Servlet context). Thus, if the load-balancer directs the second HTTP connection to another server instance, the test result will not be correct.
[top] |
Cactus provides powerful response assertion through its integration with HttpUnit. HttpUnit does support asserting page containing Javascript. However, the Cactus integration with HttpUnit currently does not support this use case (There's a bug opened for adding this support).
[top] |
StrutsTestCase is a project separate from Cactus. It has its own mailing list/forum. Please post your questions there.
[top] |
No, Cactus doesn't support HTTPS. The reason is that we don't think it's necessary. Whether you use HTTP or HTTPS should be transparent to the tested code. And you should run the tests in a test environment anyway, which doesn't necessarily need to be HTTPS just because the production environment is. Of course, if you have good arguments for HTTPS support and a patch, we might change our collective mind :-)
[top] |
You must initialize the servlet with the implicit cactus config object (see the ServletTestCase principles documentation for more details). For example:
MyServlet servlet = new MyServlet(); servlet.init(config);
[top] |