playframework: - База данных / Тестовый фреймворк / Ошибка кэширования - PullRequest
1 голос
/ 04 августа 2011

Я полностью изолировал эту проблему от очень простого игрового приложения. Я думаю, что это связано с некоторым кэшированием БД, но я не могу понять это

BasicTest.java 
========== 
import org.junit.*; 
import play.test.*; 
import play.Logger; 
import models.*; 
import play.mvc.Http.*; 
public class BasicTest extends FunctionalTest { 
    @Before public void setUp() { 
    Fixtures.deleteDatabase(); 
    Fixtures.loadModels("data.yml"); 
    Logger.debug("countFromSetup=%s",User.count()); 
    } 
    @Test 
    public void test() { 
    Response response= GET("/"); 
    Logger.debug("countFromTest=%s",User.count()); 
    assertIsOk(response); 
    } 
} 

Uncommented Configs 
================ 
%prod.application.mode=prod 
%test.application.mode=dev 
%test.db.url=jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0 
%test.db=mysql:root:xxx@t_db 
%test.jpa.ddl=create 
%test.mail.smtp=mock 
application.mode=dev 
application.name=test 
application.secret=jXKw4HabjhaNvosxgzq39to9BJECtOr39EXrEabsQAZKi7YoWAwQWo3B BFUOQnJw 
attachments.path=data/attachments 
date.format=yyyy-MM-dd 
db=mysql:root:xxx@db 
mail.smtp=mock 
Application.java 
============ 
package controllers; 
import play.*; 
import play.mvc.*; 
import models.*; 
public class Application extends Controller { 
    public static void index() { 
    Logger.debug("countFromIndex=%s",User.count()); 
    render(); 
    } 
} 
>play test 

Output of log after running the BasicTest http://localhost:9000/@tests 
================================================== 
11:54:59,008 DEBUG ~ countFromSetup=1 
11:54:59,021 DEBUG ~ countFromIndex=0 
11:54:59,034 DEBUG ~ countFromTest=1 
point to browser=> http://localhost:9000 
12:25:59,781 DEBUG ~ countFromIndex=1 

Что произошло с записью во время?Ответ ответ = GET ("/");Эта «ошибка» почти делает мои тесты бесполезными

Ответы [ 3 ]

2 голосов
/ 09 августа 2011

Вероятно, это как-то связано с транзакциями.Я однажды сталкивался с подобным случаем с парой Spring / JUnit.

Вот транзакционное выполнение теста (я думаю):

  1. Запуск транзакции t1,
  2. Выполнить настройку, результат извлекается из кеша.
  3. Выполнить тест.
  4. Запуск транзакции t2 для выполнения контроллера GET ("/")
  5. Результат извлекается из базы данных, но, поскольку t1 не был передан, он не отображается.
  6. Закрытие транзакции t2 и фиксация t1!
  7. Закрытие транзакции t1 и фиксация t2!

Кстати, это не совсем функциональный тест.Для функциональных тестов вы не должны проверять такие данные, а только статус http.Обратитесь к UnitTests для этого.Просматривая исходный код функциональных тестов, вы видите, что все реализованные проверки предназначены для проверки ответа / http.

2 голосов
/ 04 августа 2011

Я думаю, что это стандартное поведение JUnit, аннотация @Before заставляет метод запускаться перед каждым тестом:

При написании тестов обычно обнаруживается, что нескольким тестам нужны похожие объекты, созданные до того, как ониможет бежать.Аннотирование открытого метода void с помощью @Before приводит к тому, что этот метод запускается перед методом Test.Методы @Before для суперклассов будут запускаться до методов текущего класса.

From: http://junit.sourceforge.net/javadoc/org/junit/Before.html

Если вы хотите, чтобы установка запускалась после использования @BeforeClassАннотация: http://junit.sourceforge.net/javadoc/org/junit/BeforeClass.html

0 голосов
/ 05 августа 2011

В PlayFramework есть n + 1 потоков для prod и 1 поток для тестового профиля или профиля компиляции. Так что если у вас двухъядерный процессор, то есть 3 потока, если вы работаете в prod, и один поток, если вы запустили приложение с «test». Теперь еще один интересный факт: по одному Tx на исполнение. Таким образом, когда ваше приложение запускается и вы запускаете свой самый первый тест, вот что происходит:

  • Воспроизведение начинается с одного потока.
  • Запускается JUnitRunner, выполняется первый тест myTest. Это HTTP-соединение с приложением. Причина, по которой вы видите 0, заключается в GET-ответе, который выполняется перед оператором @Before.
  • @Before выполняется, создает ваши записи, и результат в @Before является точным, потому что он выполняется в том же Tx.

Поэтому я предлагаю вам либо использовать @BeforeClass, либо выполнить настройку не в @Before, а из прямого вызова в myTest для очень специфического теста с Response.

Я предполагаю, что если вы замените этот код

@Test
public void myTest() {
    Response response= GET("/test");
}

с этим

@Test
public void myTest() {
    assertEquals(1,User.count());
}

Правильно?

Так что причина, по которой вы получаете это, не ошибка. Это просто из-за этой конфигурации одного потока, которую мы имеем для тестовой среды.

Nicolas * * 1023

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