So I have this GWT code that handles RPC requests maintain states(ready, waiting, error etc).
And I would like to check if the class change its states correctly after each call, set response variables etc.
Now how should I proceed to test that without making actual requests to the server(that could run into errors in the server it self).
I think I could mock the request callback class somehow but it is invisible to the test.
I'm lost, help!
Sample of the code below(I'll post the whole thing later in case anyone wants).
public class RPCHandler
{
public RPCHandler(String method,String[] argumentsName,
String[][] argumentsValues)
{
this.method = method;
this.argumentsName = argumentsName;
this.argumentsValues = argumentsValues;
}
/**
* Method that creates a RPC request using JSON in a POST
*
*/
public void rpcRequest(){
if(currentState == HandlerState.WAITING_RESPONSE)return;
currentState = HandlerState.WAITING_RESPONSE;
// Append watch list stock symbols to query URL.
url = URL.encode(url);
url += "action=";
url += method;
// Send request to server and catch any errors.
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
String requestData = parseToJSON(argumentsName, argumentsValues);
try{
Request request = builder.sendRequest(requestData, new RequestCallback()
{
public void onError(Request request, Throwable exception)
{
setRPCException(new Exception("Error while saving. Action="+method));
setCurrentState(HandlerState.ON_ERROR);
}
//Few other error, response received hander methods after this point.
}
}
It looks like you're trying to mock out the actual transport so you should build a mock of the RequestBuilder class. In JMockit, you could write:
public class MockRequestBuilder
{
public void $init( int method, String url)
{
/* check values and/or store for later */
}
public Request sendRequest( String data, RequestCallback callback )
{
/* check values and/or store for later */
}
}
You'll need to fill in the details of the what you want the mock to do. Also, you can isolate the callback testing if you moved the callback to a named class instance inside of your outer class:
public class MyGWTClass
{
protected static class RpcCallback extends RequestCallback
{
public void onError(...) { ... }
}
}
By moving the callback object into a class and using a factory method, you can create tests that only check the callback.
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();
}
In a test, I'd like to look inside the body of a HttpRequest. I'd like to get the body as a string. It seems that the only way to do that, is to subscribe to the BodyPublisher but how does that work?
This is an interesting question. Where do you get your HttpRequest from? The easiest way would be to obtain the body directly from the code that creates the HttpRequest. If that's not possible then the next thing would be to clone that request and wraps its body publisher in your own implementation of BodyPublisher before sending the request through the HttpClient. It should be relatively easy (if tedious) to write a subclass of HttpRequest that wraps an other instance of HttpRequest and delegates every calls to the wrapped instance, but overrides HttpRequest::bodyPublisher to do something like:
return request.bodyPublisher().map(this::wrapBodyPublisher);
Otherwise, you might also try to subscribe to the request body publisher and obtain the body bytes from it - but be aware that not all implementations of BodyPublisher may support multiple subscribers (whether concurrent or sequential).
To illustrate my suggestion above: something like below may work, depending on the concrete implementation of the body publisher, and provided that you can guard against concurrent subscriptions to the body publisher. That is - in a controlled test environment where you know all the parties, then it might be workable. Don't use anything this in production:
public class HttpRequestBody {
// adapt Flow.Subscriber<List<ByteBuffer>> to Flow.Subscriber<ByteBuffer>
static final class StringSubscriber implements Flow.Subscriber<ByteBuffer> {
final BodySubscriber<String> wrapped;
StringSubscriber(BodySubscriber<String> wrapped) {
this.wrapped = wrapped;
}
#Override
public void onSubscribe(Flow.Subscription subscription) {
wrapped.onSubscribe(subscription);
}
#Override
public void onNext(ByteBuffer item) { wrapped.onNext(List.of(item)); }
#Override
public void onError(Throwable throwable) { wrapped.onError(throwable); }
#Override
public void onComplete() { wrapped.onComplete(); }
}
public static void main(String[] args) throws Exception {
var request = HttpRequest.newBuilder(new URI("http://example.com/blah"))
.POST(BodyPublishers.ofString("Lorem ipsum dolor sit amet"))
.build();
// you must be very sure that nobody else is concurrently
// subscribed to the body publisher when executing this code,
// otherwise one of the subscribers is likely to fail.
String reqbody = request.bodyPublisher().map(p -> {
var bodySubscriber = BodySubscribers.ofString(StandardCharsets.UTF_8);
var flowSubscriber = new StringSubscriber(bodySubscriber);
p.subscribe(flowSubscriber);
return bodySubscriber.getBody().toCompletableFuture().join();
}).get();
System.out.println(reqbody);
}
}
I was going through the picasso source code and came across this chunk in lines 80-94:
public interface RequestTransformer {
/**
* Transform a request before it is submitted to be processed.
*
* #return The original request or a new request to replace it. Must not be null.
*/
Request transformRequest(Request request);
/** A {#link RequestTransformer} which returns the original request. */
RequestTransformer IDENTITY = new RequestTransformer() {
#Override public Request transformRequest(Request request) {
return request;
}
};
}
From my understanding, it's somewhat declaring a variable in the interface with a static constructor. Can someone explain what is that code supposed to be doing? I read through a similar post regarding constructors in interfaces (Constructor in an Interface?) but I still don't see why this case does not apply there.
Thanks
This actually is not a variable. This is constant with anonymous implementation. Within interface it is compiled to:
public interface RequestTransformer {
Request transformRequest(Request request);
public static final RequestTransformer IDENTITY = new RequestTransformer() {
#Override
public Request transformRequest(Request request) {
return request;
}
};
}
And this is a bad practice (to have implementation within interface) :)
So I'm writing an Android application in Java based on an iOS application that I am also working on, but this question is more asking about how to communicate callback mechanism (like blocks in Objective-C 2.0) in Java.
This application involves networking, authenticating and communicating with a server via an API.
I am using this framework: https://github.com/loopj/android-async-http
I am trying to encapsulate all of the networking model into classes to make everything clean and easy (it seems so easy in iOS with delegates and blocks, but java doesn't appear to have ANY of these conveniences). So, I am using this as a guide for callbacks: http://www.gdgankara.org/2013/03/25/android-asynchronous-http-client-a-callback-based-http-client-library-for-android-and-android-smart-image-view/
Now lets say I don't want to make a call from an Activity class, but an API class, which can be called from an Activity class, how can I do this? I know easily how to do this with blocks and delegates in iOS, but how can I do this with interfaces?
For Example:
In iOS (using a common networking framework called AFNetworking), I have 4 classes:
HTTPClient.h/m
+(id)sharedHTTPClient
{
static dispatch_once_t pred = 0;
__strong static id __httpClient = nil;
dispatch_once(&pred, ^{
NSString *baseURL = http://baseurl.com;
__httpClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:baseURL]];
[__httpClient setParameterEncoding:AFJSONParameterEncoding];
});
return __httpClient;
}
APILogin.h/m
-(void)loginWithSuccessBlock:(void (^)(NSArray *responseArray))loginSuccess {
HTTPClient *httpClient = [HTTPClient sharedHTTPClient];
NSURLRequest *request = [httpClient requestWithMethod:#"GET" path:#"/api/login" parameters:nil];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSArray *response = [self.jsonParser parseResponseFromJSON:JSON];
if (loginSuccess) {
loginSuccess(response);
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
[APIErrorHandler handleError:error withHTTPResponse:response];
}];
[operation start];
}
LoginObject.h/m
-(id)init
{
self = [super init];
if(self) {
[self.apiLogin loginWithSuccessBlock:^ void (NSArray *loginArray) {
//process the array
}];
}
}
LoginVC.h/m
...
LoginObject *loginObj = [[LoginObject alloc] init];
...
So, now what I have so far, using the Android-Async-Http library is:
HTTPClient.java
public class HTTPClient extends AsyncHttpClient {
public static HTTPClient sharedHTTPClient;
public static String baseUrl = "http://baseurl.com";
public HTTPClient {
super();
}
...
}
APILogin.java
public class APILogin {
public void loginWithSuccessBlock() {
HTTPClient httpClient = QHTTPClient.sharedHTTPClient;
httpClient.get("/api/login", new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONArray response) {
// Successfully got a response
ArrayList<LoginObject> loginInfo = this.jsonParser.parseLoginFromJSON(response);
**NEED TO DO A CALL BACK!! Like with the blocks in iOS**
}
#Override
public void onSuccess(JSONObject response) {
// Successfully got a response
// shouldn't be an object
throw new IllegalArgumentException();
}
#Override
public void onFailure(Throwable e, String response) {
// Response failed :(
}
});
}
LoginObject.java
public class LoginObject {
public LoginObject {
this.apiLogin.loginWithSuccessBlock(**something something for a callback**);
}
}
Hopefully, I've made it a little clearer what I am trying to achieve. I want to be able to execute some kind of callback block on the object that called the api call, on success. However, it will not always be the same object. LoginObject may have an instance of APILogin.java and so might a different object, so I can't use the second link above in which you can specific a specific class and pass it in and call a method on it, because the classes will be of different types, and Java doesn't have a generic pointer (id or void*) object.
So I've discovered my own answer after trying many things and scouring the web for a possible solution. What I've come up with is to basically chain the response handlers.
So for:
public class APILogin {
public void loginWithSuccessBlock(**final JsonHttpResponseHandler handler**) {
HTTPClient httpClient = QHTTPClient.sharedHTTPClient;
httpClient.get("/api/login", handler);
}
}
public class LoginObject {
public LoginObject {
this.apiLogin.loginWithSuccessBlock(new JsonHttpResponseHandler(){
...
);
}
}
which isn't very robust because it doesn't let me do much customization, but it'll do.
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(...));
}