How to check whether SOAP fault is being handled gracefully? - soap

I'm using JUnit and Mockito in order to test whether my SOAP web service handles SOAP faults gracefully and doesn't throw any unwanted exceptions for example.
So up until now, as you can see from the code below, I'm only testing whether a SOAPFaultException is being thrown (of course it does, I threw it). I wonder how I could check though whether any other exception would be thrown when receiving the SOAP fault.
Also is there any way to mock a SOAP fault without throwing an exception (SOAPFaultException)?
public class SOAPFaultsTest {
private MyObj myObj = (MyObj) mock(IMockClass.class);
#Before
public void create() {
SOAPFault soapFault = null;
try {
soapFault = SOAPFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createFault();
soapFault.setFaultString("unable to create new native thread");
soapFault.setFaultCode(QName.valueOf("soap:Server"));
} catch (SOAPException e) {
e.printStackTrace();
}
// Define behaviour of myObj mock object
when(myObj.randomMethod(any(RandomClass.class))).thenThrow(new SOAPFaultException(soapFault));
}
// Here I'm testing whether invoking myObj's randomMethod with a RandomClass object as an argument throws a SOAPFaultException.
// It does because this is how I defined its behaviour.
// What I really want to test is whether receiving a SOAP fault at any time is going to cause any trouble.
#Test(expected=SOAPFaultException.class)
public void testSOAPException() throws SOAPFaultException {
RandomClass rc = new RandomClass();
myObj.randomMethod(rc);
}
}

I suggest you go with a full-stack mock (i.e. spawn an Endpoint on a local socket, point the client there). Then create a soap fault and let the mock throw an appropriate exception over the wire. If you're using CXF, I've created a simple JUnit Rule which does this, see the test method SoapServiceRuleTest.processSoapCallWithException().
As a general strategy, I suggest you make an abstract 'happy case' unit test which you then sabotage one call at a time by doing reset on the mock with each test method and adding thenThrow(..) correspondingly.

Related

Assert.Pass() throwing exception

I have a constructor as follows
public class MyClass
{
public MyClass()
{
}
}
While writing test cases, i used Assert.Pass().
But it throws an exception of type ArguementNullException
The SuccessException is a convenience for a test runner. This allows you to pass a test and record an optional message. The better way to approach this is to just let the test finish without throwing any exceptions or recording failed assertions.
More info here: http://www.nunit.org/index.php?p=utilityAsserts&r=2.5
If you're using NUnit framework,
Assert.Pass<SuccessException>();
when you want to pass a test.

JAX-RS exception handling

I'm relatively new to REST services in Java. I've created one and everything works fine except error handling. If I make a request with incorrectly formed JSON in it, Jackson JSON processor throws an exception which I unable to catch and I get error 500 in client. Exception follows:
javax.ws.rs.InternalServerErrorException: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.HashSet out of VALUE_STRING token
I have no idea how to handle exceptions raised outside my code.
Google suggests using Exception Mappers or Phase Inteceptors. Though I could miss something in search results.
What is the proper way to handle such situations?
Please, advise something. I'm stuck with this problem...
A JAX-RS ExceptionMapper should do the job. Just add a class like below to your code and if you have the exception type right, then you should get the hook to customize the handling.
#Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {
#Override
public Response toResponse(MyException ex) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}

Best way to handle constraint violations when using EJB 3.0 and CMP

I have a web service (built using jaxb/jaxws) that invokes a stateless EJB to store some data in the database. The data is being stored as an entity bean. The entity bean has a unique constraint applied to it via the #Column(unique = true) annotation.
When the web service attempts to save data, the transaction fails, and rightfully so. The problem is that since I am using CMP, the transaction is not committed until after the call to the stateless EJB. The end result is that I am not able to trap the exception and it is getting funneled up to the WS stack and results in an ambiguous fault containing the string: Error committing transaction:;nested exception is: weblogic.transaction.internal.AppSetRollbackOnlyException.
Is there a way to catch the exception being thrown so I can provide more information to the caller? Thank you.
Version information:
Application Server: Oracle Weblogic 10.3
Persistence Provider: Hibernate 3.2.5.ga (JPA 1.0)
JDK/JRE: 1.6_0_05 (provided by Weblogic install)
Update:
I tried to implement an EJB 3 interceptor around the method invocation and this does not appear to work.
public class TestInterceptor {
#AroundInvoke
public Object logCall(InvocationContext context) throws Exception {
System.out.println("Invoking method: " + context.getMethod().getName());
try {
return context.proceed();
} catch (Throwable t) {
System.out.println("I caught an exception: " + t.getMessage());
throw new Exception(t);
}
}
The reason I think this doesn't work is because the processing chain is such that the actual persist happens outside of the method (of course).
You could try using Bean Validation. It's nicely connected with the JPA (invoked during pre-persist, pre-update and pre-remove phases and can be used in different layers of your application.
Unfortunately, as far as I know, if a validation constraint violation occurs, the transaction is marked for rollback... I don't know how you could cope with that but one (seems nasty and untested) way I could think of is to inject a ValidatorFactory and validate the object by yourself. Perhaps then you could catch the ValidationException.
EDIT: I'm not sure if the Bean Validation was available in Java EE 5.
EDIT 2: You can create an interceptor which will catch the exception thrown by the JPA (or more precisely by the database). As the interceptor is invoked as a part of the same transaction as the EJB method you might need to explicitly invoke EntityManager#flush(-) to synchronise changes with the database.

GWT RequestContext ENum in the request

If we use enum as one of the attribute in the Request invocation , it throws an UnsupportedOpeationException and does not even invoke the service method on the server.
#Service(value = DesignService.class, locator = DesignServiceLocator.class)
public interface DesignRequest extends RequestContext {
Request<List<DesignProxy>> findDesign(SortEnum sortorder);
}
when we invoke the designRequest.findDesign(sortorderEnum).fire() the UnsupportOperationException is thrown on the javascript console on chrome dev tools/Firebug console.
Looks like it is related to Issue 6504, which will throw an UnsupportedOperationException if it fails to find the type you are using - consider trying to change to class methods in your enum, or wait until 2.4 is released.
If you are not using anonymous enum instances, can you post more info about this error, such as where the exception is thrown from?

How to diagnose "TestFixtureSetUp Failed"

We use TeamCity as our CI server, and I've just started seeing "TestFixtureSetUp Failed" in the test failure window.
Any idea how I go about debugging this problem? The tests run fine on my workstation (R# test runner in VS2008).
It is a bit of a flaw in the implementation of TestFixtureSetUp (and TestFixtureTearDown) that any exceptions are not well reported. I wrote the first implementation of them and I never got it to work the way it was supposed to. At the time the concepts in the NUnit code were tightly coupled to the idea that actions were directly related to a single test. So the reporting of everything was related to a test result. There wasn't really a space for reporting something that happened at the suite level without a huge re-write (it isn't a refactoring when you change a sheep into an escalator).
Because of that bit of history it's hard to find out what really happened in a TestFixtureSetUp. There isn't a good place to attach the error. The TestFixtureSetUp call is a side effect of running a test instead of being directly related to it.
#TrueWill has the right idea. Check the logs and then modify the test to add more logging if necessary. You might want to put at try/catch inside the TestFixtureSetup and log a lot in the catch block. I just thought I could add some background to it (in other words it's kind of my fault).
I'd check the Build Log first.
If it's not obvious from that, you could try including Console.WriteLines in the tests - I'm not positive, but I think those are written to the Build Log. Alternately you could log to a file (even using log4net if you wanted to get fancy).
If you have Visual Studio installed on the CI server, you could try running the build/tests from there. If it's a connectivity issue, that might resolve it.
I've seen path issues, though, where relative paths to files were no longer correct or absolute paths were used. These are harder to debug, and might require logging the paths and then checking if they exist on the build server.
I ran into this today when creating some integration tests that have long running setup that I don't want to duplicate. I ended up wrapping all the test fixture setup logic in a try/catch. I then add a SetUp method whose sole purpose is to see if a failure occurred during fixture setup and provide better logging.
Exception testFixtureSetupException = null;
[TestFixtureSetUp]
public void FixtureSetup()
{
try
{
// DoTestFixtureSetup
}
catch (Exception ex)
{
testFixtureSetupException = ex;
}
}
[SetUp]
// NUnit doesn't support very useful logging of failures from a TestFixtureSetUp method. We'll do the logging here.
public void CheckForTestFixturefailure()
{
if (testFixtureSetupException != null)
{
string msg = string.Format("There was a failure during test fixture setup, resulting in a {1} exception. You should check the state of the storage accounts in Azure before re-running the RenewStorageAccountE2ETests. {0}Exception Message: {3}{0}Stack Trace:{4}",
Environment.NewLine, testFixtureSetupException.GetType(), accountNamePrefix, testFixtureSetupException.Message, testFixtureSetupException.StackTrace);
Assert.Fail(msg);
}
}
I was getting the same error while running any test with SpecFlow using Visual NUnit. When I tried doing the same from the Unit Test Explorer(provided by Resharper), it gave a little more helpful message: Binding methods with more than 10 parameters are not supported. I realized I can't have a SpecFlow method with more than 10 params, had to remove the test.
I was able to see that I was not creating my test database correctly by doing a quick switch to VS Unit Testing. In my Case it was able to return a better response to the reason why it failed. I usually use NUnit.
"Unable to create instance of class X. Error: System.Data.SqlClient.SqlException: A file activation error occurred. The physical file name '\DbTest.mdf' may be incorrect. Diagnose and correct additional errors, and retry the operation.
CREATE DATABASE failed. Some file names listed could not be created. Check related errors..
"
Run the unit test in debug mode. You may find a runtime error in the the setup.
If you are using SpecFlow and C# in Visual Studio, look at the auto-generated <whatever>.feature.cs file after the test fails. On the public partial class <whatever>Feature line, you should see a symbol which when hovered over will show the reason that the NUnit fixture setup failed. In my case, it was that some of my BeforeFeature methods in my TestHooks class were not static. All BeforeTestRun, AfterTestRun, BeforeFeature, and AfterFeature methods need to be static.
I had this issue and it was caused by adding a private readonly Dictionary in the class, much the same way that you add a private const string.
I tried to make the Dictionary a constant but you can't do that at compile time. I solved this by putting my Dictionary in a method that returns it.
I was troubled by this today. I did the following to get the actual error.
(1) Write another test in a separate fixture which initializes an instance of the troubling test fixture, explicitly calls setup methods such as TestFixtureSetUp and SetUp if any, and then executes the target test method.
(2) Add exception handling code for the new code above, and log / output the actual exception to somewhere.
You can catch the exception and write it in the console on the TearDown
Something like:
[SetUpFixture]
public class BaseTest
{
private Exception caughtException = null;
[SetUp]
public void RunBeforeAnyTests()
{
try
{
throw new Exception("On purpose");
}
catch (Exception ex)
{
caughtException = ex;
}
}
[TearDown]
public void RunAfterAnyTests()
{
if (caughtException != null)
{
Console.WriteLine(string.Format("TestFixtureSetUp failed in {0} - {1}", this.GetType(), caughtException.Message));
}
}
}
And the result will be:
TestFixtureSetUp failed in IntegratedTests.Services.BaseTest - On purpose
I had this symptom caused by an error during field initialization. If you initialize your fields in the [SetUp] method, you should see a better error message.
[TestFixture]
internal class CommandParserTest
{
// obscure error message
private CommandParser parser = new CommandParser(...);
...
}
[TestFixture]
internal class CommandParserTest
{
private CommandParser parser;
[SetUp]
public void BeforeTest()
{
// better error message
parser = new CommandParser(...);
}
...
}