Испытание изоляции SpringBoot не гарантируется - PullRequest
0 голосов
/ 24 октября 2018

Я создал тест SpringBoot:

@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:application-dev.properties")
@Transactional
public class ContactTests2 {
    private Logger log = LogManager.getLogger();

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private ContactRepository customerRepository;

    @Autowired
    private StoreRepository storeRepository;

    @Autowired
    private NoteService noteService;

    @Autowired
    private Validator validator;

    private Store store;

    @Before
    @WithMockUser(roles = "ADMIN")
    public void setup() {
        log.debug("Stores {}", storeRepository.count());
        store = createStore();
        storeRepository.save(store);
    }

    @Test
    @WithMockUser(roles = "ADMIN")
    public void saveWithNote() {
        Contact customer = new Contact();
        customer.setPersonType(PersonType.NATURAL_PERSON);
        customer.setFirstName("Daniele");
        customer.setLastName("Rossi");
        customer.setGender(Gender.MALE);
        customer.setBillingCountry(Locale.ITALY.getCountry());
        customer.setShippingCountry(Locale.ITALY.getCountry());
        customer.setStore(store);

        Note note = new Note();
        note.setGenre(NoteGenre.GENERIC);
        note.setOperationType(AuditType.NOTE);
        note.setText("note");

        customer = customerRepository.save(customer);

        noteService.addNote(note, customer);
    }

    @Test
    @WithMockUser(roles = "ADMIN")
    public void save() {
        Contact customer = new Contact();
        customer.setPersonType(PersonType.NATURAL_PERSON);
        customer.setFirstName("Daniele");
        customer.setLastName("Rossi");
        customer.setGender(Gender.MALE);
        customer.setBillingCountry(Locale.ITALY.getCountry());
        customer.setShippingCountry(Locale.ITALY.getCountry());
        customer.setStore(store);

        customerRepository.save(customer);

        assertEquals(customer, customerRepository.findById(customer.getId()).get());
    }

    // ====================================================
    //
    // UTILITY METHODS
    //
    // ====================================================

    private Store createStore() {
        Store store = new Store();
        store.setName("Padova");
        store.setCode("PD");
        store.setCountry("IT");
        return store;
    }
}

Это служба заметок:

@Service
@Transactional
@PreAuthorize("isAuthenticated()")
public class NoteService {

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private NoteRepository noteRepository;

    /**
     * Add a note to a specific object (parent).
     * 
     * @param note
     * @param parent
     * @return the added note
     */
    public Note addNote(Note note, Persistable<Long> parent) {
        // ****************************************************
        // VALIDATION CHECKS
        // ****************************************************
        Assert.notNull(note, InternalException.class, ExceptionCode.INTERNAL_ERROR);
        Assert.notNull(parent, InternalException.class, ExceptionCode.INTERNAL_ERROR);
        // ****************************************************
        // END VALIDATION CHECKS
        // ****************************************************

        note.setParentId(parent.getId());
        note.setParentType(parent.getClass().getSimpleName());
        note.setRemoteAddress(NetworkUtils.getRemoteIpFromCurrentContext());

        note = noteRepository.save(note);

        return note;
    }
}

Я использую Hibernate и Mysql 5.7.Проблема в том, что тест называется saveWithNote().Когда я запускаю этот тест, следующие тесты не выполняются, потому что метод setup() создает дублированное исключение.Кажется, что предыдущий тест не откат.

Вот что происходит:

enter image description here

Удаление строки noteService.addNote(note, customer); все работает какОчарование.

Что я делаю не так?Почему тестовая изоляция не сохранилась?

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Скорее всего, ваша таблица использует механизм хранения MyISAM , который не поддерживает транзакции (согласно Таблица 15.2 Функции механизма хранения MyISAM документы).

Переопределение таблицыиспользуя механизм хранения InnoDB .Взгляните на 14.8.1.1 Создание таблиц InnoDB docs, по умолчанию он должен быть включен, но вы можете проверить его с помощью:

SELECT @@default_storage_engine;
0 голосов
/ 24 октября 2018

Это потому, что вы используете реальное хранилище данных в качестве зависимости.При запуске saveWithNote () запись о клиенте сохраняется в базе данных.Он не удаляется в настройках теста, поэтому при запуске save () вы сталкиваетесь с дублирующейся записью базы данных.

Решение 1: Используйте метод teardown () для удаления записей базы данныхвы создали во время теста.Пример:

    @After
    @WithMockUser(roles = "ADMIN")
    public void teardown() {
        // delete the customer entry here
    }

Ссылка: https://examples.javacodegeeks.com/core-java/junit/junit-setup-teardown-example/

Решение 2: Каждый раз, когда вы запускаете setup (), очищайте таблицы базы данных.Пример:

    @Before
    @WithMockUser(roles = "ADMIN")
    public void setup() {
        // wipe your database tables to make them empty
    }

Оба решения 1 и 2 должны выполняться только с тестовой базой данных.Вы НЕ хотите очистить производственную базу данных.

Решение 3 (рекомендуется): Использовать фиктивные репозитории и фиктивные инъекции (вместо автоподключения репозиториев с реальной реализацией),

Образец / Ссылка: https://stackoverflow.com/a/36004293/5849844

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