使用 H2 进行 Spring Boot 测试 - 未找到表“OAUTH_ACCESS_TOKEN”
Posted
技术标签:
【中文标题】使用 H2 进行 Spring Boot 测试 - 未找到表“OAUTH_ACCESS_TOKEN”【英文标题】:Spring Boot testing with H2 - Table "OAUTH_ACCESS_TOKEN" not found 【发布时间】:2020-04-19 11:55:04 【问题描述】:我想我需要先设置数据库测试环境(例如,创建表、种子用户,以便可以使用凭据颁发令牌),然后才能运行测试,但不确定如何运行。
@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = Application.class)
public class UsersControllerTest
// ...
private MockMvc mockMvc;
@Before
public void setup()
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilter(springSecurityFilterChain).build();
private String obtainAccessToken(String username, String password) throws Exception
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("client_id", CLIENTID);
params.add("grant_type", CLIENTPASSWORD);
params.add("username", username);
params.add("password", password);
ResultActions result = mockMvc.perform(post("/oauth/token")
.params(params)
.with(httpBasic(CLIENTID, CLIENTPASSWORD))
.accept("application/json;charset=UTF-8"))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"));
String resultString = result.andReturn().getResponse().getContentAsString();
JacksonJsonParser jsonParser = new JacksonJsonParser();
return jsonParser.parseMap(resultString).get("access_token").toString();
@Test
public void givenNoToken_whenGetAllUsers_thenUnauthorized() throws Exception
mockMvc.perform(
get("/users")
).andExpect(status().isUnauthorized());
@Test
public void givenToken_whenGetAllUsers_thenOk() throws Exception
String accessToken = obtainAccessToken("martyn", "secret");
mockMvc.perform(
get("/users")
.header("Authorization", "Bearer " + accessToken)
).andExpect(status().isOk());
// ...
这是此应用的典型实体:
@Entity(name = "users")
public class User implements Serializable
/**
*
*/
private static final long serialVersionUID = -8507204786382662588L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false)
private String firstName;
@Column(nullable = false)
private String surname;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
@JsonIgnore
private String password;
@OneToMany
@JoinColumn(name="user_id") // cascade = CascadeType.ALL, orphanRemoval = true
private List<Fund> funds;
public Long getId()
return id;
public String getUsername()
return username;
public void setUsername(String username)
this.username = username;
public String getPassword()
return password;
public void setPassword(String password)
this.password = password;
// standard getters and setters
public String getFirstName()
return firstName;
public void setFirstName(String firstName)
this.firstName = firstName;
public String getSurname()
return surname;
public void setSurname(String surname)
this.surname = surname;
public String getEmail()
return email;
public void setEmail(String email)
this.email = email;
public List<Fund> getFunds()
return funds;
而且,正如错误所示,我还需要生成这些 oauth* 表。
这是我的 src/test/resources/application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
所以我想我想在运行测试之前在 H2 数据库中生成表(实体和 oauth*)并填充单个用户(?)但似乎无法弄清楚这是如何在 Spring Boot 中完成的.还是我不应该完全访问任何数据库并模拟 JDBC?有人可以为我指出如何在这里准备测试环境的正确方向吗?我有点不知所措。
更新
以下是数据源的配置方式:
@Configuration
public class JDBCTokenConfig
@Value("$spring.datasource.url")
private String datasourceUrl;
@Value("$spring.datasource.username")
private String dbUsername;
@Value("$spring.datasource.password")
private String dbPassword;
@Bean
public DataSource dataSource()
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(datasourceUrl);
dataSource.setUsername(dbUsername);
dataSource.setPassword(dbPassword);
return dataSource;
@Bean
public TokenStore tokenStore(DataSource dataSource)
return new JdbcTokenStore(dataSource);
// @Bean
// public TokenStore tokenStore()
// return new InMemoryTokenStore();
//
pom.xml
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
...
</dependencies>
【问题讨论】:
看看 flyway (flywaydb.org) 或 Liquibase (liquibase.org)。两者都允许自动迁移,这也将在开发环境中触发。 感谢您的回复。这些表不是我自己的,它们属于 Spring Security 用于管理令牌。所以我不愿意为这些表编写迁移,但我知道你来自哪里。无论如何,我将发布一个略有不同但更具体的修订版。 【参考方案1】:我认为无需模拟即可访问您的内存数据库是一件好事。老实说,您将需要更多时间来配置而不是创建数据库所需的正确架构。
使用Spring-boot
,很容易配置来测试你的应用程序:
-
使用
spring-boot-starter-jpa
声明
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
-
为您的测试添加内存数据库
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
-
删除
application.properties
中的spring.datasource
属性
感谢@SpringBootApplication
,数据源将自动配置为连接到内存数据库中的 H2。
-
创建 SQL 模式
默认情况下,
spring-boot-starter-jpa
自动配置数据源以执行脚本classpath:/schema.sql
,如果您还需要,classpath:/data.sql
。
在src/test/resources
中创建一个schema.sql
,并创建表(复制以下内容,我认为这是你需要的:https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql)(我不确定这个,也许hibernate
自己创建你的架构)。
在src/test/resources/schema.sql
中创建您的架构并在src/test/resources/data.sql
中为用户播种
查看 spring 文档以了解如何配置休眠:
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#data-properties https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference现在我明白了,每个人都需要根据您的环境进行不同的配置。最好的办法是依靠配置文件。
在您的情况下,您有一个prod
个人资料和一个test
个人资料。
声明配置文件并将您的 spring.datasource
属性保存在您的 src/test/resources/application.properties
中(我认为在您的情况下更容易)
我建议您阅读此Configure specific in memory database for testing purpose in Spring,如果您在配置环境时遇到问题,请告诉我。
有了这个,你需要:
在测试类的顶部添加注释@ActiveProfiles('test')
恢复您之前删除的spring.datasource
属性并将它们放入src/test/resources/application-test.properties
告诉我
【讨论】:
感谢您的回复。我在 H2 的 pom 文件中缺少<scope>test</scope>
,所以我添加了它。我已经从 src/test/resources/application.properties 文件中删除了所有内容,但是,我现在看到以下错误 - Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.datasource.url' in value "$spring.datasource.url"
- 但对于非测试环境,我仍然需要此属性。顺便说一句,我已经更新了我的帖子以显示它的定义位置。
你能提供你的POM吗?当使用spring-boot-starter-data-jpa
或spring-boot-starter-jdbc
时,您不需要自己配置Datasource。它将被提供,您可以像使用任何其他常规 bean 一样使用这个“提供”数据源以上是关于使用 H2 进行 Spring Boot 测试 - 未找到表“OAUTH_ACCESS_TOKEN”的主要内容,如果未能解决你的问题,请参考以下文章
使用 h2database 进行 Spring boot 1.4 测试(在每个测试中回滚)
使用 H2 进行 Spring Boot 测试 - 未找到表“OAUTH_ACCESS_TOKEN”
为啥 H2 进行 spring-boot 测试,但它会将数据写入我的本地 mysql 数据库?
如何告诉 Spring Boot 使用另一个数据库进行测试?