Issue with @WithUserDetails and spring boot 1.4 TestEntityManager

送分小仙女□ 提交于 2019-12-01 06:20:07

This is an issue with timing with regard to TestExecutionListener callbacks and @Before test methods.

@WithUserDetails is supported by the Spring Security's WithSecurityContextTestExecutionListener which will never run after a @Before method. It is therefore impossible for Spring Security to see the user that you persist to the database in your setUp() method. That's basically what the exception is telling you: Spring Security attempted to read the user from the database before it existed.

One way to fix this is to migrate to @Sql support for inserting test data in the database. You might not find that as comfortable as simply persisting your entities, but the @Sql approach allows the test data to be created within the test-managed transaction (i.e., does not require manual clean up). Note that you will have to upgrade to Spring Security 4.1.1 in order for this to work properly.

An alternative way to address this is to persist your entities in a user-managed transaction in a @BeforeTransaction method -- for example, using Spring's TransactionTemplate. However, you will then need to manually clean up the database in an @AfterTransaction method in a similar fashion. Plus, you will still need to upgrade to Spring Security 4.1.1 in order for this to work.

Something like the following should do the trick:

@Autowired
private TestEntityManager testEntityManager;

@Autowired
PlatformTransactionManager transactionManager;

@BeforeTransaction
public void setUp() {
    new TransactionTemplate(transactionManager).execute(status -> {
        UserAccount owner = testEntityManager.persist(createUserAccount(OWNER_OF_ADVERTISEMENT_EMAIL));
        Language language = testEntityManager.persist(createLanguage("Français"));
        DayToTimeSlot dayToTimeSlot = testEntityManager.persist(createDayToTimeSlot());

        advertisement = testEntityManager.persist(createAdvertisement(owner, language, dayToTimeSlot));
        impersonator = testEntityManager.persist(createUserAccount(IMPERSONATOR_EMAIL));

        return null;
    });
}

@AfterTransaction
public void tearDown() {
    new TransactionTemplate(transactionManager).execute(status -> {
        testEntityManager.remove(testEntityManager.find(Advertisement.class, advertisement.getId()));

        UserAccount owner = advertisement.getUserAccount();
        testEntityManager.remove(testEntityManager.find(UserAccount.class, owner.getId()));

        testEntityManager.remove(testEntityManager.find(UserAccount.class, impersonator.getId()));

        return null;
    });
}

Regards,

Sam

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!