4

В моем приложении у меня есть набор DAO, которые я вставляю в свой прикладной уровень. Для приемочного теста, который я пишу, я хочу предварительно загрузить данные хранилища dev_server с данными, поэтому я использую ту же конфигурацию Spring в своем тесте JUnit (используя аннотацию @ContextConfiguration), чтобы вставить экземпляр соответствующего DAO в мой тест. Когда я действительно собираюсь хранить некоторые данные, например:Приемочные испытания предварительной загрузки данных в хранилище данных сервера GAE dev

dao.add(entity) 

Я получаю страшную «Никакая среда API для этой темы не зарегистрирована».

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) 
    .... 

Это, вероятно, потому, что мой тест не читал в GAE приложения-web.xml с деталями приложения (хотя я предполагаю, что здесь я мог действительно быть неправильно); поэтому он не знает, чтобы писать в тот же файл данных, что приложение, работающее на dev_server, читает/записывает.

Как я могу заставить свой тест «указывать» на то же хранилище данных, что и приложение? Есть ли какой-то механизм «источника данных», который я могу ввести как в приложение, так и в тест? Есть ли способ получить мой тест, чтобы заставить datastore api прочитать необходимую конфигурацию?

ответ

0

Я нашел решение !!!!

По какой-то причине поля пространства имен, приложения и поля AuthDomain тестового хранилища данных должны совпадать с полями dev_server, а затем dev_server может видеть объекты, вставленные в тест.

Вы можете увидеть значения для окружающей среды (dev_server или тестовый код) со следующими утверждениями

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

В экземпляра LocalServiceTestHelper (например: gaeHelper), вы можете установить значения для тестовой среды

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

Затем dev_server увидит ваши объекты. Однако из-за проблем с синхронизацией, если тест записывается в хранилище данных после запуска dev_server, dev_server не увидит его, если он не может быть вынужден перечитать файл (который я еще не понял). Иначе сервер должен быть перезапущен.

+0

К сожалению, этот подход работает только с GAE <1.4.2 (я использовал 1.4.0). Что-то в API должно было измениться между версиями, которые недействительны для этого решения. – kierans

3

Here - это страница, где рассказывается о том, как выполнять модульные тесты, которые подключаются к хранилищу данных dev. Это то, что вы ищете? В основном это говорит о двух классах: LocalServiceTestHelper и LocalDatastoreServiceTestConfig, которые вы можете использовать для настройки среды для тестирования. Хотя приведенный пример относится к модульным тестам, я считаю, что он также будет работать для вашей ситуации.

Затем вы можете настроить такие функции, как то, что файл datastore записывается на диск или просто хранится в памяти (для более быстрых тестов). Если вы хотите, чтобы эти данные переходили на то же место, что и ваш dev-сервер, вы, вероятно, захотите его отрегулировать, так как я думаю, что по умолчанию используется опция «in memory». Если вы посмотрите на javadoc, существует метод setBackingStoreLocation, где вы можете указать любой файл, который вы хотите.

+0

Я попытался настроить хранилище хранилища хранилища данных (с помощью LocalDatastoreServiceTestConfig) в тесте на тот же файл, который записывает dev_server (например: WEB-INF/appengine-generated/local_db.bin), и тест записывает объект успешно к файлу. Однако, когда я запускаю dev_server и смотрю на консоль администратора, сущность, написанная в тесте, не появляется. Если я запустил еще один тест, который запрашивает хранилище данных (с помощью LocalDatastoreServiceTestConfig), объект найден. Объект заканчивается в хранилище данных, но приложение, работающее на dev_server, не может его увидеть. – kierans

+0

Я думаю, что что-то делает с пространствами имен, которые dev_server и LocalServiceTestHelper помещают объекты в это, заставляя приложение не видеть тестовые объекты. Чтение http://code.google.com/appengine/docs/java/multitenancy/multitenancy.html Я попытался сделать тестовый код, помещая объекты в пустое ('') пространство имен, которое делает приложение, но приложение все еще не видят их. – kierans

+0

Для ясности я использовал метод NamespaceManager.set() для изменения пространства имен как в коде dev_server, так и в тестовом коде. Я также пробовал с другой строкой, но это тоже не сработало. – kierans

0

Я нашел обходное решение, хотя это не очень приятно, потому что каждый метод тестирования не очищает хранилище данных, как описано в статье Local Unit Testing for Java, однако Datastore начинает очищать каждый раз, когда запускается класс Test, поэтому это не так уж плохо, если вы будете осторожны в этом.

Проблема в том, что при использовании SpringJUnit4ClassRunner, пружинный среда создается до @Before аннотаций можно запустить, решение использовать @BeforeClass и использовать статическую переменную для LocalServiceTestHelper, чтобы они созданы до весны окружающей среды устанавливается ,

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:META-INF/spring/context-test.xml") 
@Transactional 
public class MyTest { 


    @Inject 
    private MyService myService; 

    private static final LocalServiceTestHelper helper = 
     new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()); 

    @BeforeClass 
    public static void beforeClass() { 
     helper.setUp(); 
    } 

    @AfterClass 
    public static void afterClass() { 
     helper.tearDown(); 
    } 

Если у кого-то есть лучшее решение, я буду рад слышать!