我创建了一个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()
方法抛出重复的异常。似乎以前的测试没有回滚。
会发生这种情况:
删除行noteService.addNote(note, customer);
的所有操作都像一个超级按钮。
我在做什么错?为什么不保留测试隔离?
答案 0 :(得分:1)
这是因为您使用的是真实数据存储作为依赖项。 运行saveWithNote()时,客户条目将保留在数据库中。它不会在测试设置中删除,因此在运行save()时,您会碰到重复的数据库条目。
解决方案1: 使用teardown()方法删除在测试期间创建的数据库条目。 示例:
}).then(async (app) => {
参考:https://examples.javacodegeeks.com/core-java/junit/junit-setup-teardown-example/
解决方案2:每次运行setup()时,都要擦拭干净数据库表。 示例:
@After
@WithMockUser(roles = "ADMIN")
public void teardown() {
// delete the customer entry here
}
解决方案1和2都应仅使用测试数据库来完成。您不想要清理生产数据库。
解决方案3(推荐): 使用模拟存储库和模拟注入(而不是使用实际实现自动装配存储库)。
答案 1 :(得分:1)
您的表很可能使用的MyISAM storage engine不支持事务(根据表15.2 MyISAM存储引擎功能文档)。
使用InnoDB storage engine重新定义表。看一下14.8.1.1 Creating InnoDB Tables文档,默认情况下该文档应处于启用状态,但您可以使用以下方法进行检查:
@Before
@WithMockUser(roles = "ADMIN")
public void setup() {
// wipe your database tables to make them empty
}