Dim*_*ims 42 java spring spring-mvc spring-test spring-boot
我的Spring-Boot-Mvc-Web应用程序在application.properties文件中具有以下数据库配置:
spring.datasource.url=jdbc:h2:tcp://localhost/~/pdk
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
Run Code Online (Sandbox Code Playgroud)
这是我做的唯一配置.我没有任何其他配置.尽管如此,Spring和子系统会在每次运行Web应用程序时自动重新创建数据库.数据库在系统运行时重新创建,而在应用程序结束后包含数据.
我不理解这个默认值,并期望这适合测试.
但是当我开始运行测试时,我发现数据库只重建了一次.由于测试是在没有预定义的顺序执行的,所以这是毫无意义的.
所以,问题是:如何理解?即如何在应用程序首次启动时在每次测试之前重新创建数据库?
我的测试类标题如下:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = myapp.class)
//@WebAppConfiguration
@WebIntegrationTest
@DirtiesContext
public class WebControllersTest {
Run Code Online (Sandbox Code Playgroud)
如你所见,我@DirtiesContext在课堂上尝试过并没有帮助.
UPDATE
我有一个豆子
@Service
public class DatabaseService implements InitializingBean {
Run Code Online (Sandbox Code Playgroud)
哪个有方法
@Override
@Transactional()
public void afterPropertiesSet() throws Exception {
log.info("Bootstrapping data...");
User user = createRootUser();
if(populateDemo) {
populateDemos();
}
log.info("...Bootstrapping completed");
}
Run Code Online (Sandbox Code Playgroud)
现在我做populateDemos()了清除数据库中所有数据的方法.不幸的是,它在每次测试之前都没有调用过@DirtiesContext.为什么?
Rap*_*edo 70
实际上,我想你想要这个:
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
@DirtiesContext可以用作同一类中的类级别和方法级别注释.在这种情况下,ApplicationContext将在任何此类带注释的方法之后以及在整个类之后标记为脏.如果将DirtiesContext.ClassMode设置为AFTER_EACH_TEST_METHOD,则在类中的每个测试方法之后,上下文将被标记为脏.
Zac*_*ack 51
使用 Spring-Boot 2.2.0 中接受的答案,我看到了与约束相关的 JDBC 语法错误:
引起:org.h2.jdbc.JdbcSQLSyntaxErrorException:约束“FKEFFD698EA2E75FXEERWBO8IUT”已经存在;SQL 语句:alter table foo 添加约束 FKeffd698ea2e75fxeerwbo8iut 外键 (bar) 引用 bar [90045-200]
为了解决这个问题,我添加@AutoConfigureTestDatabase到我的单元测试(spring-boot-test-autoconfigure 的一部分):
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.boot.test.context.SpringBootTest;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
@AutoConfigureTestDatabase(replace = Replace.ANY)
public class FooRepositoryTest { ... }
Run Code Online (Sandbox Code Playgroud)
jst*_*lne 12
要创建数据库,您必须执行其他答案所说的内容spring.jpa.hibernate.ddl-auto=create-drop,现在如果您的目的是在每个测试中对数据库进行傀儡,那么spring提供了非常有用的anotation
@Transactional(value=JpaConfiguration.TRANSACTION_MANAGER_NAME)
@Sql(executionPhase=ExecutionPhase.BEFORE_TEST_METHOD,scripts="classpath:/test-sql/group2.sql")
public class GroupServiceTest extends TimeoffApplicationTests {
Run Code Online (Sandbox Code Playgroud)
来自此包org.springframework.test.context.jdbc.Sql;,您可以运行before测试方法和after测试方法.填充数据库.
关于每次创建数据库,假设您只希望测试具有create-drop选项,您可以使用带有此批注的自定义属性配置测试
@TestPropertySource(locations="classpath:application-test.properties")
public class TimeoffApplicationTests extends AbstractTransactionalJUnit4SpringContextTests{
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你
Dhe*_*rik 10
如果您正在寻找 的替代品@DirtiesContext,下面的代码将对您有所帮助。我使用了这个答案中的一些代码。
首先,application.yml在测试资源文件夹中的文件上设置 H2 数据库:
spring:
datasource:
platform: h2
url: jdbc:h2:mem:test
driver-class-name: org.h2.Driver
username: sa
password:
Run Code Online (Sandbox Code Playgroud)
之后,创建一个名为的类ResetDatabaseTestExecutionListener:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Set;
public class ResetDatabaseTestExecutionListener extends AbstractTestExecutionListener {
@Autowired
private DataSource dataSource;
public final int getOrder() {
return 2001;
}
private boolean alreadyCleared = false;
@Override
public void beforeTestClass(TestContext testContext) {
testContext.getApplicationContext()
.getAutowireCapableBeanFactory()
.autowireBean(this);
}
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
if (!alreadyCleared) {
cleanupDatabase();
alreadyCleared = true;
}
}
@Override
public void afterTestClass(TestContext testContext) throws Exception {
cleanupDatabase();
}
private void cleanupDatabase() throws SQLException {
Connection c = dataSource.getConnection();
Statement s = c.createStatement();
// Disable FK
s.execute("SET REFERENTIAL_INTEGRITY FALSE");
// Find all tables and truncate them
Set<String> tables = new HashSet<>();
ResultSet rs = s.executeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='PUBLIC'");
while (rs.next()) {
tables.add(rs.getString(1));
}
rs.close();
for (String table : tables) {
s.executeUpdate("TRUNCATE TABLE " + table);
}
// Idem for sequences
Set<String> sequences = new HashSet<>();
rs = s.executeQuery("SELECT SEQUENCE_NAME FROM INFORMATION_SCHEMA.SEQUENCES WHERE SEQUENCE_SCHEMA='PUBLIC'");
while (rs.next()) {
sequences.add(rs.getString(1));
}
rs.close();
for (String seq : sequences) {
s.executeUpdate("ALTER SEQUENCE " + seq + " RESTART WITH 1");
}
// Enable FK
s.execute("SET REFERENTIAL_INTEGRITY TRUE");
s.close();
c.close();
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将重置数据库(截断表、重置序列等)并准备使用 H2 数据库。如果您使用另一个内存数据库(如 HsqlDB),您需要对 SQL 查询进行必要的更改以完成相同的操作。
之后,转到您的测试类并添加@TestExecutionListeners注释,例如:
@TestExecutionListeners(mergeMode =
TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS,
listeners = {ResetDatabaseTestExecutionListener.class}
)
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CreateOrderIT {
Run Code Online (Sandbox Code Playgroud)
这应该有效。
如果您没有看到此方法与 之间的任何性能差异@DirtiesContext,可能您正在@MockBean测试内部使用,将上下文标记为脏并自动重新加载 Spring 上下文。
使用spring boot,可以为每个测试唯一定义h2数据库。只需覆盖每个测试的数据源URL
@SpringBootTest(properties = {"spring.config.name=myapp-test-h2","myapp.trx.datasource.url=jdbc:h2:mem:trxServiceStatus"})
Run Code Online (Sandbox Code Playgroud)
这些测试可以并行运行。
在测试中,可以通过以下方式重置数据:
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
Run Code Online (Sandbox Code Playgroud)
有一个库涵盖了 JUnit 5 测试中的“重置 H2 数据库”功能:
\nhttps://github.com/cronn/test-utils#h2util
\n使用示例:
\n@ExtendWith(SpringExtension.class)\n@Import(H2Util.class)\nclass MyTest {\n\n @BeforeEach\n void resetDatabase(@Autowired H2Util h2Util) {\n h2Util.resetDatabase();\n }\n\n // tests...\n}\nRun Code Online (Sandbox Code Playgroud)\nMaven 坐标:
\n<dependency>\n <groupId>de.cronn</groupId>\n <artifactId>test-utils</artifactId>\n <version>0.2.0</version>\n <scope>test</scope>\n</dependency>\nRun Code Online (Sandbox Code Playgroud)\n免责声明:我\xe2\x80\x99m 建议库的作者。
\n| 归档时间: |
|
| 查看次数: |
48664 次 |
| 最近记录: |