A bit of newbie on Webservices, but here's a tricky one I'm struggling with finding a better way to implement. See code below: instead of having to invoke the setClientIPAddress method on each webservice method, is there a way of doing this just once ?
i.e. I tried the following:
// initialisation block
{
WSBean wsBean = new WSBean();
wsBean.setClientIPAddress(getClientIPAdd);
}
this compiles ok but I get a runtime error. Webservice class doesn't seem to like the initialisation block.
#javax.jws.WebService(targetNamespace = "http://baseentity.com/", serviceName = "WSBeanService", portName = "WSBeanPort", wsdlLocation = "WEB-INF/wsdl/WSBeanService.wsdl")
public class WSBeanDelegate {
WSBean wsBean = new WSBean();
public String getBaseInfoList(String baseID) {
wsBean.setClientIPAddress(getClientIPAdd); //
return wsBean.getBaseInfoList(transactionID);
}
public String getBaseEntityInfo(String entityID) {
wsBean.setClientIPAddress(getClientIPAdd);
return wsBean.getBaseEntityInfo(entityID);
}
#WebMethod
private String getClientIPAdd()
{
MessageContext mc = this.wsContext.getMessageContext();
HttpServletRequest req = (HttpServletRequest)mc.get("javax.xml.ws.servlet.request");
return req.getRemoteAddr();
}
I've tried using #PostContruct, as shown below:
#PostContruct
private void init()
{
wsBean.setClientIPAddress(getClientIPAdd);
}
but i get the following error: "illegalaccessexception with modifiers private".
However, declaring the method as public also requires defining the same method in the bean/wsdl file, which is not i want do do. Any suggestions on how to better this code?
Thanks in advance.
Try:
#PostContruct
#javax.jws.WebMethod(exclude=true)
public void init()
{
wsBean.setClientIPAddress(getClientIPAdd);
}
Related
Problem: I can not verify or capture an argument passed to a private method of my System under Test.
For example:
public class FooManagedBean{
public void persistFooEntity(){
Response response = new Response();
response.addResponse(checkFirstConstrain);
response.addResponse(checkSecondConstrain(response));
if(response.hasNoErros){
persistFoo();
}enter code here
}
private Response checkFirstConstrain(){
Response response = new Response();
if(//checking Constrain){
return //Response with Error
}
return //Response without Error
}
private Response checkSecondConstrain(Response response){
//some Code
}
}
First I tried to use Mockito.verify() to check the passed Response of the method checkSecondConstrain, which throws an Error, because you can only use it the Mock Instances.
Second I tried it with ArgumentCaptor in order to capture the passed Response. But here we get the same Problem because to capture the passed argument you must use Mockito.verify().
Question: Is there a way to capture or verify an argument which is passed to a private method of the System under Test? I want the state of the variable while being passed to the method.
Another Question: Is it possible to verify if a method of the System under Test is invoked or rather is never invoked?
Note: FooManagedBean is the System Under Test.
System: Java 8, Mockito 1.9.5
I would move the constraint-checking part into a separate class and make the methods public. This way, you can pass a 'ConstraintChecker' Mock and verify whatever you want.
public class ConstraintChecker {
public Response checkFirstConstraint() {
// ...
return new Response();
}
public Response checkSecondResponse() {
// ...
return new Response();
}
}
Which you then cann pass into your foo-managed-bean:
public class FooManagedBean {
private final ConstraintChecker constraintChecker;
public FooManagedBean(ConstraintChecker constraintChecker) {
this.constraintChecker = constraintChecker;
}
public void persistFooEntity() {
Response response = new Response();
response.addResponse(constraintChecker.checkFirstConstraint());
respones.addResponse(constraintChecker.checkSecondConstraint(response));
if (response.hasNoErrors()) {
persistFoo();
}
}
}
And in your test:
#Test
public void testFoo() {
ConstraintChecker constraintChecker = Mockito.mock(ConstraintChecker.class);
FooManagedBean bean = FooManagedBean(constraintChecker);
Mockito.when(constraintChecker.checkFirstConstraint()).thenReturn(new Response());
Mockito.when(constraintChecker.checkSecondResponse()).thenReturn(new Response());
bean.persistFooEntity();
Mockito.verify(constraintChecker).checkFirstConstraint();
Mockito.verify(constraintChecker).checkSecondResponse();
}
I am trying to add a advice in my application so that the onEnter and onExit gets called when a method CassandraFunctions.loadObjectByKey is invoked during execution flow. I used below code to register a advice.
protected void instrument(boolean t) {
Instrumentation instrument = null;
// Get loader initialized in premain class
try {
Class<?> c = Class.forName("my.loader.InstrumentLoader");
java.lang.reflect.Method m = c.getMethod("getInstrument");
instrument = (Instrumentation) m.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}
if(instrument == null) {
return;
}
// Add an advice
String clzName = CassandraFunctionsAdvice.class.getName();
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.named("my.functions.CassandraFunctions"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.include(Class.class.getClassLoader())
.advice(ElementMatchers.named("loadObjectByKey"), clzName))
.installOn(instrument);
}
And the advice class looks like below:
public class CassandraFunctionsAdvice {
#Advice.OnMethodEnter
public static void onEnter(#Advice.Argument(0) String key) {
String debugText = "OnMethodEnter|loadObjectByKey|key=" + key;
System.out.println(debugText);
}
#Advice.OnMethodExit
public static void onExit(#Advice.Thrown Throwable throwable) {
String debugText = "OnMethodExit|loadObjectByKey";
System.out.println(debugText);
}
}
The class that is being instrumented looks like below:
public class CassandraFunctions {
public static Object loadObjectByKey(String key) {
....
return object;
}
}
The instrumented class my.functions.CassandraFunctions is loaded much before the function loadObjectByKey is called on a user request. I am not sure what is missing and why the advice is not getting invoked.
I have already answered your question on the GitHub issue:
The advice code is just a template. The private field is not visible to the code once it is inlined by Byte Buddy.
The question you need to ask yourself is: Could I copy-paste this code to the target class and would it still compile? If no, then you need to change your advice. If you want to manage shared state, you would need to move it to a class that is accessible to the class loader(s) in question and inject it into an appropriate location.
public class Holder() {
Contact contact1;
Contact contact2;
}
public class ContactServiceImpl() {
public Contact create(Contact contact) {
// do create
}
}
public class HolderServiceImpl() {
ContactService contactService = new ContactServiceImpl();
public Holder createHolder(Holder holder) {
contactService.create(holder.getContact1());
contactService.create(holder.getContact2());
return holder;
}
}
pulbic class HolderServiceTest() {
ContactServiceImpl contactService = new ContactServiceImpl();
HolderServiceImpl holderService = new HolderServiceImpl();
#Before
public void setUp() {
contactService = EasyMock.createMock(ContactServiceImpl.class);
holderService.setContactServiceImpl(contactService);
EasyMock.expect(contactService.create(EasyMock.isA(Contact.class))).andReturn(new Contact()).anyTimes();
}
#Test
public void testCreate() {
Holder holder = new Holder();
holderService.create(holder)
}
}
When not setting the replay, I have an error on the second call of contactService.create which is IllegalStateException.
However when adding (After the expect call) :
EasyMock.replay(contactService);
I get this error:
Unexpected method call ContactServiceImpl.create(Contact#4ebd441a[
I tried using PowerMock but I get the same issue. Is it even possible to have both calls like that? Anytimes() seems to exist for that use but it's not working much.
You never did put the mock in replay state. Just add EasyMock.replay(contactService); at the end of your setUp method.
Actually what was wrong is that my method testCreate was missing the setters on contact1 and contact2 which caused the error.
I had the option of either:
Setting both objects
Using EasyMock.isNull(Contact.class) instead of EasyMock.isA(Contact.class).
However since it was possible for in real cases to have either one of them as null, the best solution was to use EasyMock.anyObject(Contact.class) which accepts both initiated objects or nulls.
#Before
public void setUp() {
contactService = EasyMock.createMock(ContactServiceImpl.class);
holderService.setContactServiceImpl(contactService);
EasyMock.expect(contactService.create(EasyMock.anyObject(Contact.class))).andReturn(new Contact()).anyTimes();
}
Im refactoring some unit tests. Basically, i ve found that unit tests of different clients implement a bundle of methods such as: createClientWithNullResponse, createClientWithSuccessResponse, etc.
I was wondering if its possible in Java to implement a generic solution to this, since this methods are repeated over and over in hundreds of unit classes, changing only the method signature.
But, there is a tricky. See a method example:
/**
* configures the client to return a succesful response
* #return a client configured to return a succesful response
*/
private Client1 configureClientWithSuccesfulResponse()
{
client = new Client1()
{
public CommonClientResponse processRequest( CommonsClientRequest commonsClientRequest )
{
CommonClientResponse commonClientResponse = new CommonClientResponse();
commonClientResponse.setResponse( new Client1Response() );
return commonClientResponse;
}
};
return client;
}
So, client2 will have the very same method except that signature have Client2, and the overrided method creates a new Client2Response, and the same with dozens of clients.
Additional information: processRequest is overrided to act as a mock, setting the response i wish for each method.
Client1 extends CommonsWS that extends of AbstractCommons, which is an abstract class but contains the implementation of processRequest method.
All in all, my idea is to create a Base class for all unit tests, with a bundle of generic methods where i can pass the class type, and then rewrite the processRequest for each one. Ive tried :
public class base <T extends AbstractCommonClient>{
private T configureClientWithNullResponse(Class <? extends AbstractCommonClient> clazz, Class< ? extends ClientResponse> clazz1)
{
try
{
return clazz.newInstance()
{
CommonClientResponse processRequest( CommonsClientRequest commonsClientRequest )
{
CommonClientResponse commonClientResponse = new CommonClientResponse();
commonClientResponse.setResponse( clazz1.newInstance() );
return commonClientResponse;
};
};
}
}
}
but it not even compile. Do you have any ideas of how i can begin implementing this?
As you are effectively trying to create an anonymous class whose type is unknown at runtime, have you considered invoking the compiler at runtime? I haven't used it much myself, but it may be worth investigating. You can invoke it by using
JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler();
Note that this will only work if the application is run on a system where JDK is install, as JRE (does not include javac).
This is a tricky question. I suggest create a Factory class that would return each type of client, and you provide the response and pass it to the factory. Something like:
public class ClientFactory {
public static createResponse(ClientResponse response) {
CommonClientResponse commonClientResponse = new CommonClientResponse();
commonClientResponse.setResponse(response);
return commonClientResponse;
}
public static Client1 createClient1(final ClientResponse response) {
return new Client1() {
public CommonClientResponse processRequest(CommonsClientRequest unused) {
return createResponse(response)
};
}
};
public static Client2 createClient2(final ClientResponse response) {
return new Client2() {
public CommonClientResponse processRequest(CommonsClientRequest unused) {
return createResponse(response)
};
}
};
..... // same for every type of Client
And you call it using:
factory.createClient1(new Client1Response());
There is still some duplication, but it helps. A little.
What do you think?
I would like to know what's the best approach to test the method "pushEvent()" in the following class with a jUnit test.
My problem is, that the private method "callWebsite()" always requires a connection to the network. How can I avoid this requirement or refactor my class that I can test it without a connection to the network?
class MyClass {
public String pushEvent (Event event) {
//do something here
String url = constructURL (event); //construct the website url
String response = callWebsite (url);
return response;
}
private String callWebsite (String url) {
try {
URL requestURL = new URL (url);
HttpURLConnection connection = null;
connection = (HttpURLConnection) requestURL.openConnection ();
String responseMessage = responseParser.getResponseMessage (connection);
return responseMessage;
} catch (MalformedURLException e) {
e.printStackTrace ();
return e.getMessage ();
} catch (IOException e) {
e.printStackTrace ();
return e.getMessage ();
}
}
}
Stubbing
You'll need a test double (stub) to allow isolated, easy, unit testing. The following is non tested, but demonstrates the idea. The use of Dependency Injection will allow you to inject at test time, a test version of your HttpURLConnection.
public class MyClass()
{
private IHttpURLConnection httpUrlConnection;
public MyClass(IHttpURLConnection httpUrlConnection)
{
this.httpUrlConnection = httpUrlConnection;
}
public String pushEvent(Event event)
{
String url = constructURL(event);
String response = callWebsite(url);
return response;
}
}
Then you create a stub (sometimes referred to as a mock object) to be the stand in for the concrete instance.
class TestHttpURLConnection : IHttpURLConnection { /* Methods */ }
You'll also construct a concrete version, for your production code to use.
class MyHttpURLConnection : IHttpURLConnection { /* Methods */ }
Using your test class (an adapter) you are able to specifiy what should happen during your test. A mocking framework will enable you to do this with less code, or you can manually wire this up. The end result of this for your test is that you'll set your expectations for your test, for example, in this case you may set OpenConnection to return a true boolean (This is just an example by the way). Your test will then assert that when this value is true, the return value of your PushEvent method matches some expected result. I've not touched Java properly for a while, but here are some recommended mocking frameworks as specified by StackOverflow members.
Possible solution: You can extend this class, override callWebsite (you have to make it protected for this purpose) - and the override method write some stub method implementation.
Approaching things from a slightly different angle...
I'd worry less about testing this specific class. The code in it is extremely simple and, while a functional test to make sure it's working with a connection would be helpful, a unit level test "may" not be necessary.
Instead, I'd focus on testing the methods it calls that appear to actually do something. Specifically...
I'd test constructURL method from this line:
String url = constructURL (event);
making sure that it can construct a URL properly from different Events, and throws Exceptions when it should (possibly on an invalid Event or null).
And I'd test the method from the following line:
String responseMessage = responseParser.getResponseMessage (connection);
Possibly pulling out any "get information out of the connection" logic into one proc, and leaving only "parse said information" in the original one:
String responseMessage = responseParser.getResponseMessage(responseParser.getResponseFromConnection(connection));
or something along those lines.
The idea being to put any "must deal with external data sources" code in one method, and any code logic in separate methods that can be easily tested.
As an alternative to Finglas's helpful answer with respect to mocking, consider a stubbed approach where we override the functionality of callWebsite(). This works quite well in the case where we aren't so interested in the logic of callWebsite as that of the other logic called within pushEvent(). One important thing to check is that callWebsite is calledwith the correct URL. So, first change is to the method signature of callWebsite() to become:
protected String callWebsite(String url){...}
Now we create a stubbed class like this:
class MyClassStub extends MyClass {
private String callWebsiteUrl;
public static final String RESPONSE = "Response from callWebsite()";
protected String callWebsite(String url) {
//don't actually call the website, just hold onto the url it was going to use
callWebsiteUrl = url;
return RESPONSE;
}
public String getCallWebsiteUrl() {
return callWebsiteUrl;
}
}
And finally in our JUnit test:
public class MyClassTest extends TestCase {
private MyClass classUnderTest;
protected void setUp() {
classUnderTest = new MyClassStub();
}
public void testPushEvent() { //could do with a more descriptive name
//create some Event object 'event' here
String response = classUnderTest.pushEvent(event);
//possibly have other assertions here
assertEquals("http://some.url",
(MyClassStub)classUnderTest.getCallWebsiteUrl());
//finally, check that the response from the callWebsite() hasn't been
//modified before being returned back from pushEvent()
assertEquals(MyClassStub.RESPONSE, response);
}
}
Create an abstract class WebsiteCaller which would be a parent of ConcreteWebsiteCaller and WebsiteCallerStub.
This class should have one method callWebsite (String url). Move your callWebsite method from MyClass to ConcreteWebsiteCaller. And MyClass will look like:
class MyClass {
private WebsiteCaller caller;
public MyClass (WebsiteCaller caller) {
this.caller = caller;
}
public String pushEvent (Event event) {
//do something here
String url = constructURL (event); //construct the website url
String response = caller.callWebsite (url);
return response;
}
}
and implement method callWebsite in your WebsiteCallerStub in some way appropriate for testing.
Then in your unit test do something like this:
#Test
public void testPushEvent() {
MyClass mc = new MyClass (new WebsiteCallerStub());
mc.pushEvent (new Event(...));
}