2014-12-19 4 views
0

Я тестирую слой DAO в Spring MVC + Hibernate + HSQLDB, и я не могу дважды загрузить список воспроизведения из базы данных.Не удается получить элементы из базы данных дважды

Не знаю, почему я получаю размер List как 0. Метод testSavePlaylist успешно, но метод test_getPlaylistById не работает. Когда я тестирую только один метод, он отлично работает.

Трассировка Ошибка:

java.lang.AssertionError: expected:<2> but was:<0> 
at org.junit.Assert.fail(Assert.java:88) 
at org.junit.Assert.failNotEquals(Assert.java:743) 
at org.junit.Assert.assertEquals(Assert.java:118) 
at org.junit.Assert.assertEquals(Assert.java:555) 
at org.junit.Assert.assertEquals(Assert.java:542) 
at adrian.example.musicplayer.dao.music.PlayListImplDaoTest.test_getPlaylistById(PlayListImplDaoTest.java:44) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:606) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

Junit Класс

@RunWith(SpringJUnit4ClassRunner.class) 
@WebAppConfiguration 
@ContextConfiguration 
@Transactional 
public class PlayListImplDaoTest { 

    @Autowired 
    PlayListDao playlistDao; 

    private static boolean setUpIsDone = false; 

    @Before 
    public void setUp() throws Exception { 
     if(setUpIsDone) { 
      return; 
     } 
     this.playlistDao.savePlaylistForJunit(); 

     setUpIsDone = true; 
    } 

    @Test 
    public void test_getPlaylistById() throws InterruptedException { 
     List<Playlist> testedPlaylist = (List<Playlist>) this.playlistDao.getPlaylistById(1); 
     assertEquals(2, testedPlaylist.size()); 
    } 

    @Test 
    public void testSavePlaylist() throws InterruptedException { 
     this.playlistDao.savePlaylist(1, "TestPlaylist2"); 
     List<Playlist> testedPlaylist2 = (List<Playlist>) this.playlistDao.getPlaylistById(1); 
     assertEquals(2, testedPlaylist2.size()); 
    } 
} 
+0

Кроме использования переменной 'boolean' для продолжения работы' setUp() 'более одного раза, используйте' @ BeforeClass' вместо '@ Before'. Таким образом, он запускается один раз для всего класса перед любыми тестами, а не один раз перед каждым методом тестирования. – t0mppa

+0

@ t0mppa '@ BeforeClass' не подходит для этого случая, потому что метод' setUp() 'нуждается в переменной переменных playlistDao, полученной (автоматически) из полностью инициализированного контекста приложения. Поэтому 'setUp()' не может быть статическим. –

+0

@LukasRisko: Хорошая уловка, я бы просто добавил прямое манипулирование DB в тестовый класс, хотя вместо того, чтобы иметь DAO, заполненный кодом, используемым только для тестирования. – t0mppa

ответ

3

Я считаю, что поведение по умолчанию для транзакционных тестов JUnit в весной откатить после каждого испытания. Таким образом, некогда выпадающее количество БД, которое вы делаете в setUp(), возвращается после первого теста, что приводит к неудаче второго теста, потому что база данных теперь пуста.

Вы можете изменить это поведение, аннотируя тестовый класс @TransactionConfiguration(defaultRollback=false).

Тем не менее, можно считать неудачной практикой проведение тестов на состояние, когда данные сохраняются после одного теста, с возможностью воздействия на результаты следующего и получения разных результатов на основе порядка выполнения.

Вместо этого вам может быть лучше удалить «если» из вашего setUp() и повторно заново заполнить вашу БД за каждый тестовый проход.

3

Вы аннулировали свой класс как @Transactional, что означает, что каждый метод @Test будет выполнен в рамках транзакции. Метод, аннотированный с помощью @Before, выполняется перед каждым из методов тестирования, но в рамках той же транзакции, что и метод тестирования. Помните, что для тестовой среды значение @TransactionConfiguration(defaultRollback = true). Так что, если вы запускаете тесты один из многих возможных сценариев:

  1. новая транзакция открыта
  2. всего setUp() выполняется, что означает, что некоторые тестовые данные создаются с использованием this.playlistDao.savePlaylistForJunit() и после того, что флаг setUpIsDone установлен в правда
  3. testSavePlaylist() выполняются успешно, поскольку есть данные испытания
  4. транзакция откатывается назад, что означает, что тестовые данные, созданные this.playlistDao.savePlaylistForJunit() ушли
  5. новых сделок Тион открыт
  6. метод установки является то, рано возвращается как setUpIsDone правда на данный момент
  7. test_getPlaylistById() выполняется, но нет никаких данных тестов, доступных
  8. транзакция откатывается назад

Для получения дополнительной информации смотрите на the section Spring Testing Annotations of the Spring Reference Documentation

Смежные вопросы