Тестирование заказанного CRUD в jUnit

Я хочу протестировать операции CRUD в своих jUnit тестах. Я хотел бы сделать это в некотором порядке, где testCreate будет вставлять запись в базу данных, а testRead, testUpdate, testDelete будет работать с данными, которые уже вставлены testCreate. Сейчас пытаюсь сделать что-то подобное.

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public abstract class UserPersistenceTest {

    @PersistenceContext
    protected EntityManager entityManager;

    @Inject
    protected UserTransaction utx;

    protected Collection<User> entities;

    @Rule
    public ExternalResource resource = new ExternalResource() {
        @Override
        protected void before() throws Exception {
            System.out.println("Setting up resource");
            entities = generateEntities(); // returns a list of User
            prepareTests();
        }
        @Override
        protected void after() {
            System.out.println("Cleaning up resource");
            try {
                utx.rollback();
            } catch (SystemException e) {
                e.printStackTrace();
            }
        }
    };

    @Deployment
    public static Archive<?> createDeployment() {
        return Deployments.createDeployment();
    }

    public void prepareTests() throws Exception {
        utx.begin();

        System.out.println("Inserting records...");

        for (User e : entities) {
            entityManager.persist(e);
        }
    }


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



    @Test
    public void testCreate() throws Exception {
        // insert records
        for (User e : entities) {
            entityManager.persist(e);
        }

        // validate that they're there
        testRead();
    }


    @Test
    public void testRead() {
        JPAQuery q = new JPAQuery(entityManager);

        List<User> retrieved = q.from(e).list(e);

        Assert.assertEquals(entities.size(), retrieved.size());
        Assert.assertTrue(retrieved.containsAll(entities));
    }

Теперь странно, что READ,UPDATE,DELETE тест не работает, если я не вставляю записи до тестовых случаев, т.е. метод prepareTests(). Они просто не видят вставленных записей, как будто был какой-то автоматический откат. CREATE работает. Однако, если записи вставлены до CREATE, все будет работать.

Мой вопрос: почему другие тесты не «видят» изменения, которые сделал testCreate (вставил записи)? Я убедился, что он действительно запускается перед другими тестами. Но они нормально это видят, если их вставляет метод before().

Что здесь происходит? Как я могу сообщить другим моим тестам о вставке testCreate?


person wesleyy    schedule 23.02.2018    source источник


Ответы (1)


Причиной «какого-то автоматического отката» является ваша реализация after-метода ExternalResource.

Этот метод выполняется после каждого теста (метод, а не класс), см. здесь например.

Итак, вы делаете в основном

before() <-Insert's done here
testCreate() <- More Insert's done here
after() <- Rollback happens here
before() <- Insert's done here again
testRead() <- Insert's from testCreate have been rolled back in last after()
after() <- Rollback again

Как вы видите, записи, вставленные testCreate, откатываются до того, как произойдет testRead().

Если вы хотите сделать что-то вроде того, что вы предложили, вы можете откатить транзакцию в методе @AfterClass (и вставить в @BeforeClass)

Другой альтернативой может быть вставка записей в метод before() метода ExternalResource.

person tom    schedule 23.02.2018