M. le Rutte
M. le Rutte

Reputation: 3563

How to mock answers of the Google App Engine services (e.g. blobstore)

I'm trying to create a unit test for my Google App Engine project. The use case is as follows: a client queries the API for an upload URL, as the data needs to be stored in the blobstore, the client recieves a JSON encoded structure with the URL. The client then uploads the data to that URL.

The implementation of the servlet is fairly simple:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
    Gson gson = new Gson();
    Map<String, String> result = new HashMap<String, String>();
    result.put("uploadurl", BlobstoreServiceFactory.getBlobstoreService()
            .createUploadUrl("/api/v1/import"));
    gson.toJson(result, resp.getWriter());
}

In good fashion there should be a test to see whether the client does indeed receive the right data. So there should be a counter JUnit test. I was hoping to mock the blob store service so that it would return a fixed upload url, which the test then can check.

However, I have no idea how to overrule the blobstore service. Using Mockito I can't mock the static getBlobstoreService(), using the LocalBlobstoreServiceTestConfig I have no idea how I can overrule the answer to createUploadUrl().

My attempt to write a test was something like this:

public class ImportServletTest {
   public static class Response {
    String uploadurl;

    void setUploadurl(String url) {
        this.uploadurl = url;
    }
}

private LocalBlobstoreServiceTestConfig blobstoreConfig = new LocalBlobstoreServiceTestConfig();

private LocalServiceTestHelper helper = new LocalServiceTestHelper(blobstoreConfig);
@Test
public void getsUploadURL() throws IOException, ServletException {
    ImportServlet servlet = new ImportServlet();

    HttpServletResponse response = mock(HttpServletResponse.class);
    try (CharArrayWriter output = new CharArrayWriter();
            PrintWriter writer = new PrintWriter(output);) {
        when(response.getWriter()).thenReturn(writer);

        servlet.doGet(null, response);
        writer.flush();

        Response apiResponse = new Gson().fromJson(output.toString(), Response.class);
        assertEquals("http://mysite/_ah/theurl", apiResponse.uploadurl);
    }
}

@Before
public void setupGae() throws IOException {
    helper.setUp();
}

@After
public void teardownGae() {
    helper.tearDown();
}
}

Upvotes: 1

Views: 719

Answers (1)

Skice
Skice

Reputation: 461

Mocking static classes/methods is in general very dangerous (http://googletesting.blogspot.it/2008/12/static-methods-are-death-to-testability.html), but in a similar case I had some success using PowerMock (https://code.google.com/p/powermock/) to override the behavior of static classes that were not under my control. I guess you'll have to mock the entire method chain:

BlobstoreServiceFactory.getBlobstoreService().createUploadUrl()

to return a custom URL instead of that generated by the BlobStore.

Upvotes: 1

Related Questions