Search code examples
springgoogle-app-engineautomated-testsacceptance-testing

Acceptance testing preloading of data into GAE dev server datastore


In my application I have a set of of DAOs which I inject into my application layer. For an acceptance test I'm writing, I want to preload the dev_server datastore with data, so I use the same Spring config in my JUnit test (using the @ContextConfiguration annotation) to inject an instance of the relevant DAO into my test. When I actually go to store some data eg:

dao.add(entity)

I get the dreaded "No API environment is registered for this thread."

Caused by: java.lang.NullPointerException: No API environment is registered for this thread.
 at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppId(DatastoreApiHelper.java:108)
 at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppIdNamespace(DatastoreApiHelper.java:118)
    ....

This is probably because my test case hasn't read in the GAE application-web.xml with the app details (although I'm guessing here I could really be wrong); so it doesn't know to write to the same datastore that the app running on the dev_server is reading/writing to.

How can I get my test to "point" to the same datastore as the app? Is there some "datasource" mechanism that I can inject both into the app and the test? Is there a way to get my test to force the datastore api to read the needed config?


Solution

  • I've found the solution!!!!

    For some reason the Namespace, AppID and the AuthDomain fields of the test datastore have to match that of the dev_server, then the dev_server can see the entities inserted by the test.

    You can see the values for the environment (dev_server or test code) with the following statements

    System.out.println(NamespaceManager.get());
    System.out.println(ApiProxy.getCurrentEnvironment().getAppId());
    System.out.println(ApiProxy.getCurrentEnvironment().getAuthDomain());
    

    In your instance of LocalServiceTestHelper (eg: gaeHelper), you can set the values for the test environment

    // the NamespaceManager is thread local.
    NamespaceManager.set(NamespaceManager.getGoogleAppsNamespace());
    gaeHelper.setEnvAppId(<the name of your app in appengine-web.xml>);
    gaeHelper.setEnvAuthDomain("gmail.com");
    

    Then the dev_server will see your entities. However because of synchronisation issues, if the test writes to the datastore after the dev_server has been started the dev_server wont see it unless it can be forced to reread the file (which I haven't figured out yet). Else the server has to be restarted.