我开发了一个系统,其基础设施层是在Spring启动(Security,Data JPA,MVC ...)上开发的。在运行时,系统连接到MySQL,其设置在src/main/resources/application.properties
以及.sql,其中包含一些用户插入和角色以进行身份验证。
对于集成测试,我决定使用HSQLDB隔离数据并执行“安全”测试。为此,我创建了类AbstractIntegrationTest
,其中包含用于创建和清理要从控制器进行测试的表和方法的方法。所有测试类都扩展它:(我隐藏了不涉及数据库的方法)
@WebAppConfiguration
@ContextConfiguration(classes={LibraryManagerContextConfiguration.class, WebSecurityConfig.class})
public class AbstractIntegrationTest {
@Autowired
private WebApplicationContext webApplicationContext;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private LoginFilter loginFilter;
private MockMvc mockMvc;
private static IDatabaseConnection databaseConnection;
private static Connection connection;
private static boolean isAfterFirstRun;
private static Logger logger = LogManager.getLogger(AbstractIntegrationTest.class);
@BeforeClass
public static void createDatabase() throws Exception {
try {
final Properties properties = loadProperties();
final String driver = properties.getProperty("datasource.driver");
final String url = properties.getProperty("datasource.url");
final String userName = properties.getProperty("datasource.username");
final String password = properties.getProperty("datasource.password");
final String schema = properties.getProperty("datasource.schema");
Class.forName(driver);
connection = DriverManager.getConnection(url, userName, password);
databaseConnection = new HsqldbConnection(connection, schema);
} catch (final SQLException exception) {
throw new RuntimeException(exception.getMessage(), exception);
} catch (final ClassNotFoundException exception) {
throw new RuntimeException(exception.getMessage(), exception);
}
}
@Before
public void setDatabaseUp() throws Exception {
if (!isAfterFirstRun) {
runSQLCommands(getDataSetupFile());
}
runSQLCommands(getClearDatabaseFile());
runSQLCommands(getResetSequencesFile());
runSQLCommands(getDataFile());
isAfterFirstRun = true;
}
@AfterClass
public static void closeConnection() throws Exception {
connection.close();
databaseConnection.close();
}
protected void runSQLCommands(final String file) throws Exception {
if (file != null) {
final InputStream stream = getSQLInputStream(file);
final BufferedReader databaseReader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
int i = 1;
String sqlStatement = null;
while ((sqlStatement = databaseReader.readLine()) != null) {
if (sqlStatement.startsWith("--")) {
i++;
continue;
}
final int index = sqlStatement.lastIndexOf(";");
if (index > -1) {
sqlStatement = sqlStatement.substring(0, index + 1);
}
if (sqlStatement.trim().length() != 0) {
try {
connection.createStatement().execute(sqlStatement);
logger.info(sqlStatement);
} catch (final Exception exception) {
logger.error("Error running command on line " + i + " of file " + file + ": " + exception.getMessage());
throw new RuntimeException(exception);
}
}
i++;
}
}
}
protected IDatabaseConnection getConnection() {
return databaseConnection;
}
protected static IDataSet getDataSet(final String dataset) {
try {
final InputSource source = new InputSource(AbstractIntegrationTest.class.getResourceAsStream(dataset));
return new FlatXmlDataSetBuilder().build(source);
} catch (final Exception exception) {
throw new RuntimeException("Cannot read the dataset file " + dataset + "!", exception);
}
}
private static Properties loadProperties() throws Exception {
final InputStream stream = ClassLoader.getSystemResourceAsStream("datasource.properties");
if (stream == null) {
throw new FileNotFoundException("File erm.properties not found. A file named erm.properties must be present "
+ "in the src/test/resources folder of the project whose class is being tested.");
}
final Properties properties = new Properties();
properties.load(stream);
return properties;
}
private static InputStream getSQLInputStream(final String fileName) {
return AbstractIntegrationTest.class.getResourceAsStream(fileName);
}
protected String getClearDatabaseFile() {
return "/database/clear-database.sql";
}
protected String getDataSetupFile() {
return "/database/database-setup.sql";
}
protected String getDataFile() {
return "/database/data.sql";
}
protected String getResetSequencesFile() {
return "/database/reset-sequences.sql";
}
}
LibraryManagerContextConfiguration
和WebSecurityConfig
类包含域和基础结构bean声明,因此它们构成了spring上下文。
此类位于src/test/java
中,datasource.properties
文件与测试.sql一起位于src/test/resources
中。测试类运行完美,测试脚本运行,表创建,但是当测试库在测试期间查找某些数据时,它会搜索MySQL而不是HSQLDB。这是一个测试类:
@RunWith(SpringJUnit4ClassRunner.class)
public class AuthenticationIntegrationTest extends AbstractIntegrationTest {
@Test
public void shouldGetAuthorizationJwt() throws Exception {
final String jsonCredentials = "{"
+ "\"username\" : \"augusto\","
+ "\"password\" : \"spring\""
+ "}";
final MvcResult result = performRESTLogin(jsonCredentials);
final MockHttpServletResponse response = result.getResponse();
final int status = response.getStatus();
final String jwt = response.getHeader("Authorization");
assertThat(status, is(200));
assertThat(jwt, notNullValue());
}
}
当我使用仅存在于测试数据库中的用户名和密码并且获得403
状态而MySQL状态获得200
状态时,我验证了这一点。
看来,在编写HSQLDB之后,将读取main的.properties和.sql并覆盖正在使用的数据库的设置。
application.properties:
server.contextPath=/librarymanager
server.port: 8081
spring.datasource.url = jdbc:mysql://localhost:3306/librarymanager
spring.datasource.username = root
spring.datasource.password = root
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = create-drop
spring.jpa.hibernate.naming.strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
datasource.properties:
datasource.class=org.hsqldb.jdbc.JDBCDataSource
datasource.driver=org.hsqldb.jdbc.JDBCDriver
datasource.url=jdbc:hsqldb:mem:librarymanager;sql.syntax_ora=true
datasource.schema=sa
datasource.username=sa
datasource.password=
pom.xml中的数据库依赖关系:
<!-- Banco de dados -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
执行成功的缺失是什么?使用注释?创建.properties for dev和tests与BDs conf和主要.properties与spring.profiles.active = dev/test
分开以在配置文件之间切换?我想要一些建议。
感谢。
github中的项目链接:https://github.com/augustodossantosti/librarymanager-jwtauth
答案 0 :(得分:0)
感谢您的建议。实际上使用框架是最好的选择。