AndroidAnnotations how to use setBearerAuth - android

I'm trying to authenticate with a REST API via a token using AndroidAnnotations #Rest RestClient Interface.
But due to a lack of documentation I can't get it running using setBearerAuth(String token);
I already have the interface and the class HeadersRequestInterceptor implements ClientHttpRequestInterceptor, but I don't know where to call setBearerAuth(myCustomToken);
If someone could give me a hint I would be very graceful.
Cheers

MyRestClient.java:
#RequiresAuthentication
#Rest(rootUrl = "your_url", converters = {...})
public interface MyRestClient extends RestClientHeaders {
#Post("/somecall")
public void someApiCall();
}
MyActivity.java:
#EActivity
public class MyActivity extends Activity {
#RestService
MyRestClient client;
#Background
void callSomeApi() {
String accessToken = ... ; // was previously returned from server
client.setBearerAuth(accessToken);
client.someApiCall(); // it will add header: Authorization: Bearer accessToken
}
}

I found out a better way, let-me explain:
If you need to apply that in all your Android REST calling, so we need to create a Interceptor to get all REST request made by the application like this:
import android.content.Context;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EBean;
import org.androidannotations.annotations.RootContext;
import org.androidannotations.rest.spring.annotations.Rest;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
/**
* Created by Rafael Rocha on 21/05/2018.
*/
#EBean
public class HttpBasicAuthenticatorInterceptor implements ClientHttpRequestInterceptor {
#RootContext
Context context;
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().add("Authorization",AUTHENTICATION_SCHEME + "your_token_goes_here");
return execution.execute(request, body);
}
}
Replace AUTHENTICATION_SCHEME by your authentication method, in my case was "Bearer" and don't forget to put a blank space between them "Bearer YOUR_TOKEN".
After that is just put a reference in your REST service class on #Rest annotation filling the property "interceptors"
import org.androidannotations.rest.spring.annotations.Accept;
import org.androidannotations.rest.spring.annotations.Get;
import org.androidannotations.rest.spring.annotations.Header;
import org.androidannotations.rest.spring.annotations.Path;
import org.androidannotations.rest.spring.annotations.Rest;
import org.androidannotations.rest.spring.api.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.util.List;
/**
* Created by Rafael Rocha on 13/03/2018.
*/
#Rest(rootUrl = RestUtil.ROOT_URL, converters = {MappingJackson2HttpMessageConverter.class}, interceptors = {HttpBasicAuthenticatorInterceptor.class})
#Accept(MediaType.APPLICATION_JSON)
public interface NotificationRest {
//#Header(name = "server_version", value = SERVER_VERSION)
#Get("notificacao/profissional/recentes/{idProfessional}")
List<ResponseNotification> getNotifications(#Path Long idProfessional);
}
The only thing I did was put a Header value in the request header. You can do it to pass other things for example here in my application a need to pass my application android version to server side treats the old application or simply block the access, so I just need to increase on more line in the code
request.getHeaders().add(RestUtil.SERVER_VERSION_HEADER,RestUtil.SERVER_VERSION);

Related

Class has no public constructor TestCase(String name) or TestCase() while running my Cucumber scenario

I'm using Green Coffee library to run Cucumber scenarios in my instrumentation tests. I followed example provided by repo step-by-step, but here's the error:
junit.framework.AssertionFailedError: Class pi.survey.features.MembersFeatureTest has no public constructor TestCase(String name) or TestCase()
And when I try to add default constructor to the class like provided here, it says
no default constructor available in
'com.mauriciotogneri.greencoffee.GreenCoffeeTest'
Here's my test's source code:
package pi.survey.features;
import android.support.test.rule.ActivityTestRule;
import com.mauriciotogneri.greencoffee.GreenCoffeeConfig;
import com.mauriciotogneri.greencoffee.GreenCoffeeTest;
import com.mauriciotogneri.greencoffee.Scenario;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.IOException;
import pi.survey.MainActivity;
import pi.survey.steps.memberSteps;
#RunWith(Parameterized.class)
public class MembersFeatureTest extends GreenCoffeeTest {
#Rule
public ActivityTestRule<MainActivity> activity = new ActivityTestRule<>(MainActivity.class);
public MembersFeatureTest(Scenario scenario) {
super(scenario);
}
#Parameterized.Parameters
public static Iterable<Scenario> scenarios() throws IOException {
return new GreenCoffeeConfig()
.withFeatureFromAssets("assets/members.feature")
.scenarios();
}
#Test
public void test() {
start(new memberSteps());
}
}
And my members.feature source:
Feature: Inserting info to server
Scenario: Invalid members
When I introduce an invalid members
And I press the login button
Then I see an error message saying 'Invalid members'
Regarding the questions about the constructors. Due to the fact that tests in GreenCoffee require:
#RunWith(Parameterized.class)
The static method annotated with #Parameters must return a list of something (but not necessarily Scenario). The examples in the documentation simply return a list of scenarios, that's why the constructor must take a single Scenario as a parameter.
However, you can create a class that encapsulates the scenario and other objects that you may need to pass to the constructor. For example, given the following class:
public class TestParameters
{
public final String name;
public final Scenario scenario;
public TestParameters(String name, Scenario scenario)
{
this.name = name;
this.scenario = scenario;
}
}
You can write:
public TestConstructor(TestParameters testParameters)
{
super(testParameters.scenario);
}
#Parameters
public static Iterable<TestParameters> parameters() throws IOException
{
List<TestParameters> testParametersList = new ArrayList<>();
List<Scenario> scenarios = new GreenCoffeeConfig()
.withFeatureFromAssets("...")
.scenarios();
for (Scenario scenario : scenarios)
{
testParametersList.add(new TestParameters(scenario.name(), scenario));
}
return testParametersList;
}
In this way you can receive multiple values (encapsulated in an object) in the test constructor.
Solved problem by just fixing the structure.
code details in this commit

Powermock keeps returning me a null object not a mock

So I am looking at the mocking objects in a test.
However the following test will return npe when " Mockito.when(mock.getName()" portion of code is executed, thats because the mock object is returned as null.
package com.example.activity;
import com.example.BuildConfig;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import static org.junit.Assert.assertTrue;
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21)
#PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
#PrepareForTest(Static.class)
public class DeckardActivityTest {
#Rule
public PowerMockRule rule = new PowerMockRule();
#Mock
public ToBeMocked mock;
#Test
public void testSomething() throws Exception {
assertTrue(Robolectric.buildActivity(DeckardActivity.class).create().get() != null);
}
#Test
public void testStaticMocking() {
PowerMockito.mockStatic(Static.class);
Mockito.when(Static.staticMethod()).thenReturn(mock);
Mockito.when(mock.getName()).thenReturn("Mock");
assertTrue(Static.getResp().equals("Mock"));
}
}
and the simple class we are testing
package com.example.activity;
public class Static {
private static ToBeMocked toBeMocked;
public static ToBeMocked staticMethod() {
toBeMocked = new ToBeMocked();
return toBeMocked;
}
public static String getResp(){
return toBeMocked.getName();
}
}
So my understanding must be wrong.
What I would like to do is mock out the ToBeMocked class dependency give it and tell the mock object how to respond when getName method is called on it.
Can some one help me as to why this is going wrong or point out what I must have misunderstood
Yes, you understand it wrong. I mean you have misunderstanding how mocks work.
Your method getResp (in example) uses internal states which will not be set at all, because after you call PowerMockito.mockStatic(Static.class); all calls of static methods of the Static.class will be intercepted. So the code:
toBeMocked = new ToBeMocked();
return toBeMocked;
never is called.
If the getResp uses the staticMethod() then you code will work.
public static String getResp(){
return staticMethod().getName();
}
So you have two option to resolve your issue:
refactor your code as I pointed
use mock constructor to mock toBeMocked = new ToBeMocked();

Error in connecting App Engine backend to Async Task

I am trying to write a backend service in Android, which reads a remote database and executes a query on it, returning the result in a ResultSet object. This is the code for my Java Bean which I return from the API call (called SQLResult):
package com.gradai.rushhour.backend;
import java.sql.ResultSet;
public class SQLResult
{
ResultSet result;
public SQLResult()
{
}
public ResultSet getResult()
{
return result;
}
public void setResult(ResultSet rs)
{
result = rs;
}
}
Now I try to use this API (called sqlBackend) in an AsyncTask in the actual app. In the onPostExecute function, I am getting an error:
error: incompatible types: com.gradai.rushhour.backend.sqlBackend.model.ResultSet cannot be converted to java.sql.ResultSet
This is the code for the said function:
protected void onPostExecute(SQLResult result)
{
ResultSet rs = result.getResult();
Toast toast = Toast.makeText(context, rs.toString(), Toast.LENGTH_LONG);
toast.show();
}
I don't get why is a ResultSet class being created in the backend model. Please help me in understanding what is going on. I'll be glad to provide further code if needed for debugging.
EDIT: These are the import statements used in the AsyncTask program:
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.json.gson.GsonFactory;
import com.gradai.rushhour.backend.sqlBackend.SqlBackend;
import com.gradai.rushhour.backend.sqlBackend.model.SQLResult;
import java.io.IOException;
import java.sql.ResultSet;
Also, please note that: I tried to convert the ResultSet in the API function to an ArrayList, and changed the SQLResult class to contain the same. Now, when I try to access the ArrayList in the same function, I get the error that a List is expected instead of an ArrayList. Could that be helpful?

Android Spring Rest Template using MockRestServiceServer with Build tool 1.1

I using Spring Android Rest Template to perform HTTP request. I was testing like so :
package com.mnubo.platform.android.sdk.internal.user.services.impl;
import com.mnubo.platform.android.sdk.models.users.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.web.client.MockRestServiceServer;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
#RunWith(RobolectricTestRunner.class)
#Config(emulateSdk = 18)
public class DummyTest {
private MyApiImpl myApi;
private MockRestServiceServer myapiMockServer;
#Before
public void setUp() throws Exception {
myApi = new MyApiImpl("ACCESS_TOKEN");//break here
myapiMockServer = MockRestServiceServer.createServer(myApi.getRestTemplate());
}
#Test
public void testRestClient() throws Exception {
final User expectedUser = new User();
expectedUser.setUsername("test");
expectedUser.setLastname("lastname");
myapiMockServer.expect(requestTo("http://my-service.com/user/test"))
.andExpect(method(GET))
.andRespond(withSuccess(this.convertToJsonString(expectedUser), APPLICATION_JSON_UTF8));
User user = myApi.userOperations().getUser("test");
userMockServer.verify();
}
}
All of this was working correctly using the RoboelectricTestRunner. But, yesterday Android Studio updated and asked me to update the build tool version to 1.1.0. (com.android.tools.build:gradle:1.1.0).
This version now include supports for Unit testing. See https://sites.google.com/a/android.com/tools/tech-docs/unit-testing-support
The problem : I can't create MyApiImpl anymore because it creates a RestTemplate. This RestTemplate use org.springframework.http.client.HttpComponentsClientHttpRequestFactory and in this class constructor, methods from the org.apache.http package are used.
These methods raised an exception : Eg: Method getSocketFactory in org.apache.http.conn.scheme.PlainSocketFactory
Well, I mocked successfully the getSocketFactory using PowerMock but then I had to mock the register method of SchemeRegistry that is only locally accessible from the constructor (source).
So I gave up trying to mock all of the shenanigans happening inside the RestTemplate and decided to directly mock the RestTemplate.
I need help to mock it correctly so that the MockRestServiceServer can still be used in my test, because right now, the myapiMockServer.verify() assertion fails.
Update
I'm still unable to use the MockRestServiceServer to test my Api, but I managed to test each individual OperationImpl using a mock of the RestTemplate like so :
public class DummyOperationTest {
private DummyOperation dummyOperation;
private RestTemplate mockedRestTemplate = mock(RestTemplate.class);
#Before
public void setUp() throws Exception {
super.setUp();
dummyOperation = new DummyOperationImpl(PLATFORM_BASE_URL, mockedRestTemplate);
}
#Test
public void test() throws Exception {
String calledUrl = PLATFORM_BASE_URL + "/objects?update_if_exists=true";
when(mockedRestTemplate.postForObject(calledUrl, expectedSmartObject, SmartObject.class)).thenReturn(expectedSmartObject);
smartObjectService.create(expectedSmartObject, true);
verify(mockedRestTemplate, atMost(1)).postForObject(calledUrl, expectedSmartObject, SmartObject.class);
}
}
Unfortunately, this still doesn't test the whole request execution. I can't validate that oAuth authentication is correctly added to the headers, or if the conversion of the server response is correct.
Well, it was a matter of mocking. I didn't understood everything correctly but I finally worked it out. Here is an a example that shows how to proceed :
package com.mnubo.platform.android.sdk.internal;
import android.util.Log;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.test.web.client.MockRestServiceServer;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.mockito.PowerMockito.whenNew;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
#RunWith(PowerMockRunner.class)
#PrepareForTest({
Log.class,
PlainSocketFactory.class,
SSLSocketFactory.class,
HttpComponentsClientHttpRequestFactory.class,
ConnManagerParams.class,
AbstractHttpClient.class
})
public class DummyTest {
private final String USER_ACCESS_TOKEN = "user_token";
private final PlainSocketFactory mockedPlainSocketFactory = mock(PlainSocketFactory.class);
private final SSLSocketFactory mockedSSLSocketFactory = mock(SSLSocketFactory.class);
private final SchemeRegistry mockedSchemeRegistry = mock(SchemeRegistry.class);
private final DefaultHttpClient mockedHttpClient = mock(DefaultHttpClient.class);
private final HttpParams mockedHttpParams = mock(HttpParams.class);
private DummyApiImpl dummyApi = new DummyApiImpl(USER_ACCESS_TOKEN);
protected MockRestServiceServer mockServer;
#Before
public void setUp() throws Exception {
mockStatic(Log.class);
mockStatic(PlainSocketFactory.class);
mockStatic(SchemeRegistry.class);
mockStatic(SSLSocketFactory.class);
mockStatic(ConnManagerParams.class);
whenNew(SchemeRegistry.class).withAnyArguments().thenReturn(mockedSchemeRegistry);
whenNew(DefaultHttpClient.class).withAnyArguments().thenReturn(mockedHttpClient);
when(PlainSocketFactory.getSocketFactory()).thenReturn(mockedPlainSocketFactory);
when(SSLSocketFactory.getSocketFactory()).thenReturn(mockedSSLSocketFactory);
when(mockedHttpClient.getParams()).thenReturn(mockedHttpParams);
mockServer = MockRestServiceServer.createServer(dummyApi.getRestTemplate());
}
#Test
public void doOperationTest() throws Exception {
final User testUser = new User();
mockUserServiceServer.expect(requestTo(expectedUrl("/users/test")))
.andExpect(method(POST))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andRespond(withSuccess());
dummyApi.userOperations().createUser("test", testUser);
mockUserServiceServer.verify();
}
}
The problem occurred when the constructor of the Api was called. This classe extends AbstractOAuth2ApiBinding which constructor create a RestTemplate. This is this object that requires multiple level of mocking.
Once you have mocked the required element to create the RestTemplate, the rest is very easy, thanks to the mock server!

Android reflection doesn't work - it don't find any class

I have an Android application.
I want to scan for all classes within a package for a specify annotation.
I have:
package com.sample.package;
import com.sample.core.Controller;
import com.sample.core.ProtocolId;
#Controller
public class OtherController implements ControllerInterface{
#ProtocolId(id=100)
public void doSomething(){
//do something
}
}
I'm finding for classes annotated with #Controller for a specify #ProtocolId number.
I'm using Google Reflections library.
Here is how I'm scanning:
package com.sample.package;
import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
import com.sample.core.Controller;
import com.sample.core.ProtocolId;
public class FrontController {
public void executeProperControllerMethodBasedOnId(){
Reflections ref = new Reflections("com.sample.package");
Set<Class<?>> classes = ref.getTypesAnnotatedWith(Controller.class);
System.out.println(classes.size()); //THE SIZE IS 0!!!
//The reflection doesn't worked! It didn't found any class!
}
}
The above code doesn't find any class annotated with specify annotation. Is
there something which I miss when I'm using google reflection library on
android?

Categories

Resources