How to write tests for API based on Google Cloud Endpoints? - java

Is there some way to test API written using Google Cloud Endpoint using JUnit or other framework?
In documentation there is an example using curl commands and perhaps the logic behind this is to test API on client side only.
When I tried to find some approaches how to test API from server-side, I came across the possibility of writing JUnit tests and invoking HttpURLConnection's to localhost, but there are problems with this approach. For example, the instance of app engine should be already running before testing, but I deploy locally with maven and testing is prior deploying, so if I have broken tests it doesn't deploy dev server and I do not feel that that is the right way to rewrite maven steps.
Edit 1: Found something similar for Python: How to unit test Google Cloud Endpoints

With Objectify you can do it like this. For example, let's declare our BooksEndpoint as follows:
#Api(
name = "books",
version = "v1",
namespace = #ApiNamespace(ownerDomain = "backend.example.com", ownerName = "backend.example.com", packagePath = "")
)
public class BooksEndpoint {
#ApiMethod(name = "saveBook")
public void saveBook(Book book, User user) throws OAuthRequestException, IOException {
if (user == null) {
throw new OAuthRequestException("User is not authorized");
}
Account account = AccountService.create().getAccount(user);
ofy().save()
.entity(BookRecord.fromBook(account, book))
.now();
}
}
To test it, you would need following dependencies:
testCompile 'com.google.appengine:appengine-api-labs:1.9.8'
testCompile 'com.google.appengine:appengine-api-stubs:1.9.8'
testCompile 'com.google.appengine:appengine-testing:1.9.8'
testCompile 'junit:junit:4.12'
Now, test will look as follows:
public class BooksEndpointTest {
private final LocalServiceTestHelper testHelper = new LocalServiceTestHelper(
new LocalDatastoreServiceTestConfig()
);
private Closeable objectifyService;
#Before
public void setUp() throws Exception {
testHelper.setUp();
objectifyService = ObjectifyService.begin(); // required if you want to use Objectify
}
#After
public void tearDown() throws Exception {
testHelper.tearDown();
objectifyService.close();
}
#Test
public void testSaveBook() throws Exception {
// Create Endpoint and execute your method
new BooksEndpoint().saveBook(
Book.create("id", "name", "author"),
new User("example#example.com", "authDomain")
);
// Check what was written into datastore
BookRecord bookRecord = ofy().load().type(BookRecord.class).first().now();
// Assert that it is correct (simplified)
assertEquals("name", bookRecord.getName());
}
}
Note, I'm using BookRecord and Book here - those are my Entity and POJO, nothing special.

First, thanks for the link to the Python answer. Regarding Java, this Udacity course is based around a Google Cloud Endpoints project in Java, and it has many code examples on how to test endpoints. The source code is here. I have been trying to reproduce the project in Python, and I unfortunately cannot provide any details based on personal experience with testing endpoints written in Java, but I hope the links help!

Related

I need help running a unit test for jsonschema2pojo

I have a question regarding unit testing of jsonschema2pojo.
What I am trying to do is use the sample unit test in https://github.com/joelittlejohn/jsonschema2pojo/blob/master/jsonschema2pojo-integration-tests/src/test/java/org/jsonschema2pojo/integration/json/RealJsonExamplesIT.java
to set up my own test, however I find that there is no test library available. I tried to set up the sources in my project, but I am not using Maven, but Gradle. For the lack of Maven, the class or.jsonschema2pojo.integration.util.JsonSchema2PojoRule class does not want to compile without Maven in my project. In our team we do not use maven in our build server.
I hope that someone can help me point in the direction of how I would unit test my implementation method.
This is the unit test I am trying to run:
public class AnalyticsGeneratorImplTest extends AbstractGoogleAnalyticsTest {
// Set a logger
private static Logger log = LoggerFactory.getLogger(AnalyticsGeneratorImplTest.class);
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
#Rule
public JsonSchema2PojoRule schemaRule = new JsonSchema2PojoRule();
#Test
public void getTitleFromGeneratedJson() throws Exception {
//verify that the incoming Json has been transformed
ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/assets/generated-list/google-analytics.json", "uk.ac.soton.generators.analytics.target",
config("sourceType", "json",
"useLongIntegers", true));
Class<?> googleAnalyticsJsonObject = resultsClassLoader.loadClass("uk.ac.soton.generators.analytics.serialised.GoogleAnalyticsJsonObject");
Object gaJsonObj = OBJECT_MAPPER.readValue(this.getClass().getResourceAsStream("/assets/generated-list/google-analytics.json"), googleAnalyticsJsonObject);
Object result = googleAnalyticsJsonObject.getMethod("getResult").invoke(gaJsonObj);
Object data = result.getClass().getMethod("getData").invoke(result);
Object title = data.getClass().getMethod("getTitle").invoke(data);
assertThat(title.getClass().getMethod("getTitle").invoke(title).toString(), is("blue"));
}
}
You need add the dependecies in gradle:
compile group: 'org.jsonschema2pojo', name: 'jsonschema2pojo-gradle-plugin', version: '0.4.29'
And the others one. If there exist in Maven, it can exist in Gradle too. Check in MavenRepository and select the dependecie you want and Will be exist for all Java Build Toll just select the Gradle Tab and you see the dependecie you need. org.jsonschema2pojo

Java Play 2.4 write test case for class using injection

Recently I am using play 2.4 framework for Java project.
In that I am using WsClient Library. That library is injected in my class.
#Inject WSClient wsClient
Now I am trying to write a test case for that class but test case fails because of null pointer error for wsClient variable.
wsClient.url("some url").get()
Can you please help me to resolve this?
following is the test code
// Class
public class ElasticSearch {
#Inject WSClient wsClient;
public Promise<WSResponse> createIndex() {
Logger.info("Entering ElasticSearch.createIndex()");
Logger.debug("WSClient: " + wsClient);
Promise<WSResponse> response =wsClient.url(this.getEsClient()+ "/" +this.getEsIndexName()).setContentType("application/json").put("");
Logger.info("Exiting ElasticSearch.createIndex()");
return response;
}
}
// Test function
#Test
public void testCreateIndex() {
running(fakeApplication(), new Runnable() {
public void run() {
ElasticSearch esearch= new ElasticSearch();
esearch.setEsIndexName("car_model");
assertNotNull(esearch.createIndex());
}
});
}
Before writing the options you have, I suggest to use elastic4s.
This third party lib will help you write a more functional code and give you very nice dsl to write your queries.
One more thing, I don't know what is your used case for using elasticsearch, but I recommend using a different client then the rest api, which will give you more secure connection and more efficient.
You get the NPE, because you instasiate ElasticSearch by your own with new, and don't let guice to the wiring for you, this is why the WSClient is null.
Now for your options,
You have 2 options:
Add WithApplication to your test, which will basically load your application, this will give you the access to Guice injector, from which you can take ElasticSearch class like this you have couple of ways to do it:
As described in play documentation using
import play.api.inject.guice.GuiceInjectorBuilder
import play.api.inject.bind
val injector = new GuiceInjectorBuilder()
.configure("key" -> "value")
.bindings(new ComponentModule)
.overrides(bind[Component].to[MockComponent])
.injector
val elasticsearch = injector.instanceOf[ElasticSearch]
By importing Play
import play.api.Play
val elasticsearch = Play.current.injector.instanceOf(classOf[ElasticSearch])
Using FakeApplication: just get hold of the fake application injector, and use it to get an instance of ElasticSearch class.
I don't like the above options, because you need an application running, which can make your tests very slow.
I suggest to create the WSClient by your self and instantiate ElasticSearch class with it, and run your tests.
val httpClient = NingWSClient.apply()
val elasticsearch = new ElasticSearch(httpClient)
This is a more light solution, and should make your tests run faster.

How to make a library act as a no-op in Debug mode?

This question pertains specifically to Flurry, but I'd be curious how to do it for any 3rd party language.
Essentially, Flurry is causing a crash in Robolectric (as per: https://github.com/robolectric/robolectric-gradle-plugin/issues/144) and the only way I can get my unit tests to work is to remove all calls to Flurry (e.g. FlurryAgent.init, FlurryAgent.onStartSession, etc...).
Short of putting all of these under a BuildConfig.Debug 'if' block (which means having a lot of them), is there any way to globally cause all calls to FlurryAgent compile as no-ops in debug mode, for example?
LeakCanary is a good example of the effect I would like to see.
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
}
We are also using Flurry. So for the rest of application Flurry is hidden by our Analytics class and this helps us easy to mock it and verify interaction with it.
To test Analytics itself we use another technics:
public class Analytics {
...
protected startFlurry(Context context, String apiKey) {
FlurryAgent.onStartSession(context, apiKey);
}
...
}
And the test:
public class AnalyticsTest {
...
#Before
protected setUp() {
analytics = new Analytics();
analyticsSpy = spy(analytics);
doNothing().when(analyticsSpy).startFlurry(any(Context.class), anyString());
}
...
}
This is workaround but I don't have better solution for now.

How to stand up then shut down a Solr instance in a Unit Test?

I am writing camel unit test. One service that I interface with is Solr. After testing with mocks, I want to write tests that bring up a local solr instance.
So far I have tried to leverage the RestTestBase Solr class (org.apache.solr.util.RestTestBase). Because I am writing a unit test, I have not extended the class, merely tried to use the static methods it provides. The following does not work:
RestTestBase.createJettyAndHarness("src/test/resources/solr",
"solrconfig.xml", "schema.xml",
"/solr", true, null);
int solrPort = RestTestBase.jetty.getLocalPort();
String solrURL = "localhost:"+Integer.toString(solrPort)+"/solr";
...
I included solr and jetty in my pom. Any suggestions for how to programmatic stand up and shut down a solr instance? (because i am using camel unit testing, i prefer not to extend RestTestBase)
see the camel-solr unit tests for some complete examples....SolrComponentTestSupport
basically this...
#BeforeClass
public static void beforeClass() throws Exception {
// Set appropriate paths for Solr to use.
System.setProperty("solr.solr.home", "src/test/resources/solr");
System.setProperty("solr.data.dir", "target/test-classes/solr/data");
// Instruct Solr to keep the index in memory, for faster testing.
System.setProperty("solr.directoryFactory", "solr.RAMDirectoryFactory");
// Start a Solr instance.
solrRunner = new JettySolrRunner("src/test/resources/solr", "/solr", getPort());
solrRunner.start();
solrServer = new HttpSolrServer("http://localhost:" + getPort() + "/solr");
}
#AfterClass
public static void afterClass() throws Exception {
if (solrRunner != null) {
solrRunner.stop();
}
}

JUnit Test of Code that uses GAE/J URLFetchServiceFactory.getURLFetchService()

I've got some code I'm deploying to Google App Engine - Java (GAE/J) that makes use of the URLFetchService. I'd like to use JUnit to test this code. Per the testing documentation, it appears I should have a test that uses their LocalURLFetchServiceTestConfig class ROUGHLY as follows:
public class MyRemoteServiceTests {
private static final LocalURLFetchServiceTestConfig urlConfig = new LocalURLFetchServiceTestConfig();
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(urlConfig);
#Before
public void setUp() throws Exception {
service = new SampleService();
helper.setUp();
}
#After
public void tearDown() throws Exception {
service = null;
helper.tearDown();
}
#Test
public void testThatCallsCodeThatUsesUrlFetch() {
Object data = service.getRemoteDataUsingUrlFetch("foo", "bar");
Assert.assertNotNull(data);
}
}
I'm finding that this test continues to fail despite using the "helper" as suggested in the GAE/J documentation on testing: "The API package 'urlfetch' or call 'Fetch()' was not found.".
I was assuming that using the "helper" would somehow setup the GAE environment such that when I call URLFetchServiceFactory.getURLFetchService() from within my getRemoteDataUsingUrlFetch method, the interface returned would be an instance of LocalURLFetchService that would just "work" but that seems NOT to be the case.
How can I test this code?
Am I missing something? (I'm pretty new to GAE...)
Do I have to refactor my getRemoteDataUsingUrlFetch so that it doesn't use URLFetchServiceFactory.getURLFetchService() because that makes it untestable locally??? (That sounds like it would really suck...)
Any help/suggestions much appreciated!
Actually, it turns out my problem was failure to include two additional jars that ARE mentioned on the Local Unit Testing page of the documentation. RTM FTW!
appengine-local-runtime.jar
appengine-api-stubs.jar
afaik, the LocalURLFetchService doesn't configure the GAE like you expect. It is more of a way to fetch URL from the local dev and then process the contents however. (Similarly even the LocalDatastoreService and LocalMemcacheService operate on isolated spaces within the test environment)
One way to test your code is to refactor the getRemoteDataUsingUrlFetch() to take maybe the contents of the Url response. somewhat like,
URLFetchResponse resp = LocalURLFetchService.fetch(status, request)
getRemoteDataUsingUrlFetch(foo, bar, resp)

Categories