Google App Engine: модульное тестирование одновременного доступа к memcache - PullRequest
3 голосов
/ 25 апреля 2010

Не могли бы вы, ребята, показать мне способ имитации одновременного доступа к memcache в Google App Engine? Я пытаюсь с LocalServiceTestHelpers и потоков, но не повезло. Каждый раз, когда я пытаюсь получить доступ к Memcache в потоке, я получаю эту ошибку:

ApiProxy$CallNotFoundException: The API package 'memcache' or call 'Increment()' was not found

Я полагаю, что библиотека тестирования GAE SDK пыталась имитировать реальную среду и, таким образом, настроить среду только для одного потока (потока, в котором выполняется тест), который не может быть просмотрен другим потоком.

Вот фрагмент кода, который может воспроизвести проблему

package org.seamoo.cache.memcacheImpl;

import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.tools.development.testing.LocalMemcacheServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;

public class MemcacheTest {
 LocalServiceTestHelper helper;

 public MemcacheTest() {
  LocalMemcacheServiceTestConfig memcacheConfig = new LocalMemcacheServiceTestConfig();
  helper = new LocalServiceTestHelper(memcacheConfig);
 }

 /**
  * 
  */
 @BeforeMethod
 public void setUp() {
  helper.setUp();
 }

 /**
  * @see LocalServiceTest#tearDown()
  */
 @AfterMethod
 public void tearDown() {
  helper.tearDown();
 }

 @Test
 public void memcacheConcurrentAccess() throws InterruptedException {
  final MemcacheService service = MemcacheServiceFactory.getMemcacheService();
  Runnable runner = new Runnable() {

   @Override
   public void run() {
    // TODO Auto-generated method stub
    service.increment("test-key", 1L, 1L);
    try {
     Thread.sleep(200L);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    service.increment("test-key", 1L, 1L);
   }
  };

  Thread t1 = new Thread(runner);
  Thread t2 = new Thread(runner);
  t1.start();
  t2.start();
  while (t1.isAlive()) {
   Thread.sleep(100L);
  }
  Assert.assertEquals((Long) (service.get("test-key")), new Long(4L));
 }
}

Ответы [ 4 ]

5 голосов
/ 26 апреля 2010

Вы пытаетесь протестировать свое приложение или реализацию memcache в App Engine? Семантика memcache при одновременном чтении и записи хорошо понятна - вам лучше просто смоделировать условия, которые могут возникнуть, чтобы убедиться, что ваше приложение хорошо с ними справляется.

2 голосов
/ 09 марта 2015

Проблема в том, как настроены потоки, и ее можно решить с помощью ThreadManager, предоставленного в SDK:

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

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

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

AtomicInteger threadsRemaining = new AtomicInteger(NUM_USERS);
AtomicInteger numFailingThreads = new AtomicInteger(0);

@Test
public void testManyUsers() throws Exception {


    ArrayList<TestUser> testUsers = new ArrayList<TestUser>();

    // Create something to test in parallel (in this case a "user")
    for (int i = 0; i < NUM_USERS; ++i) {
        testUsers.add(new TestUser());
    }

    // Fork off a thread for each user
    runInParallel(testUsers);

    // Wait for threads to complete.
    while (threadsRemaining.intValue() != 0) {
        Thread.sleep(10); // TODO: Clean up with callbacks or whatever. 
    }

    assertEquals(numFailingThreads.intValue(), 0);
}

private void runInParallel(final ArrayList<TestUser> testUsers) {


    for (final TestUser u : testUsers) {

        Runnable myTask = new Runnable() {

            @Override
            public void run() {
                try {

                    // The user tries to kill my server

                } catch (Exception e) {

                    // The user triggered badness in my server

                    e.printStackTrace();
                    numFailingThreads.incrementAndGet();
                }
                threadsRemaining.decrementAndGet();
            }
        };

        ThreadFactory threadFactory = ThreadManager.currentRequestThreadFactory();

        Thread t = threadFactory.newThread(myTask);

        t.start();
    }


}
1 голос
/ 25 апреля 2010

GAE не поддерживает пользовательские потоки. Я думаю, что вы пытаетесь слишком усложнить.

Один из способов проверить это - создать внешний многопоточный клиент и создать столько потоков, сколько вы хотите для удаленного доступа к GAE. Если он работает на вашем локальном компьютере, просто укажите там.

0 голосов
/ 25 апреля 2010

Я полагаю, что библиотека тестирования GAE SDK пытался имитировать реальный среда и, таким образом, настроить среда только для одного потока ( нить что запускает тест) который не виден другим потоком.

Это предположение примерно верное: поскольку GAE сам по себе никогда не запускает несколько потоков в одном процессе, следовательно, так же, как и SDK, - поэтому мне не ясно, почему вы хотите протестировать многопоточный доступ, которого просто не может быть в GAE .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...