Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data + SpringBootTest: How to mock SecurityContext for JPA auditing?

In a Spring Boot application I want to test (JUnit 5) the persistence layer with enabled auditing (@EnableJpaAuditing). I use Liquibase to setup a H2 db and Hibernate as the JPA implementation.

@Configuration
//@EnableTransactionManagement
@EnableJpaAuditing
//@EnableJpaRepositories
public class MyPersistenceConfig {
}

My entity has the following fields:

@CreatedDate
@Column(name = "CREATED_AT", updatable = false)
private Instant createdAt;

@CreatedBy
@Column(name = "CREATED_BY", updatable = false)
private String createdBy;

@CreatedDate
@Column(name = "LAST_MODIFIED_AT")
private Instant lastModifiedAt;

@CreatedBy
@Column(name = "LAST_MODIFIED_BY")
private String lastModifiedBy;

I have the following dependencies:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.liquibase</groupId>
        <artifactId>liquibase-core</artifactId>
        <scope>runtime</scope>
        <!--<scope>test</scope>-->
    </dependency>

    <!-- Testing -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>test</scope>
    </dependency>

I tried several combinations of annotations:

@SpringBootTest //(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//@DataJpaTest
@ContextConfiguration(classes = MyPersistenceConfig.class)
@EnableAutoConfiguration
//@SecurityTestExecutionListeners
//@Import(SpringBootWebSecurityConfiguration.class)
@WithMockUser(username = "test", password = "test", roles = "USER")
@ExtendWith(SpringExtension.class)
class MyRepositoryTest {

    @Autowired
    private MyRepository testee;

...
}

But whatever I try, either the repository is null (autowiring) or I get an exception when inserting an entry:

NULL not allowed for column "CREATED_BY"; SQL statement:

I guess I need a SecurityContext (which isn't available for autowiring currently).

What is the easiest way to provide a mock SecurityContext that works with auditing and @WithMockUser?

like image 877
Puce Avatar asked Nov 17 '22 13:11

Puce


1 Answers

This is an old question but for those who may stumble upon it trying to get Spring Data auditing to work in their integration tests this may help. The auditing functionality requires an AuditingAware bean to get the current user. In DataJpaTest this seems to be missing. One way to make it available is adding a @Bean configuration to your test.

@RunWith(SpringRunner.class)
@DataJpaTest
@Import({DatabaseIntegrationTest.TestConfig.class})
@WithMockUser
class DatabaseIntegrationTest {

  @TestConfiguration
  static class TestConfig {
    @Bean
    public AuditorAware<String> auditorAware() {
      return () -> Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication().getName());
    }
  }
}
like image 148
Mustafa Avatar answered Dec 21 '22 12:12

Mustafa