2017-04-11 80 views
1

我开发了一个系统,其基础架构层是在Spring引导(安全性,数据JPA,MVC ...)上开发的。在运行时,系统连接到MySQL,其设置位于src/main/resources/application.properties以及包含一些用户插入和角色以进行身份​​验证的.sql。
对于集成测试,我决定使用HSQLDB来隔离数据并执行“安全”测试。为此我创建了类AbstractIntegrationTest,其中包含创建和清理要从控制器进行测试的表和方法的方法。所有测试类扩展它:(我不涉及数据库的隐藏方法)用于在弹簧启动应用程序中进行集成测试的内存数据库配置(HSQLDB)

@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"; 
    } 

} 

LibraryManagerContextConfigurationWebSecurityConfig类包含的领域和基础设施豆类声明,以他们做了Spring上下文。

本课程是在src/test/javadatasource.properties文件以及测试.sql在src/test/resources。测试类运行良好,运行测试脚本,创建表,但是当Repository在测试期间查找某些数据时,它将搜索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= 

DB依赖在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> 

执行失败失败的原因是什么?使用注释?为dev和测试创建.properties,并使用BDs conf和主要.properties与spring.profiles.active = dev/test在配置文件之间切换?我想提出一些建议。

感谢。在github上

项目链接:https://github.com/augustodossantosti/librarymanager-jwtauth

+1

我认为它更好地使用不同的属性为不同的环境,以避免这种混淆。 application-test.properties,application-prod.properties – CrazyMac

+0

您正在使它变得复杂...只需提供一个单独的属性文件进行测试,其中包含hsqldb的信息,加载该文件以覆盖其他属性...使用框架不反对它。此外,您不应该为每个测试重新创建数据库,进行测试'@ Transactional',并在测试完成后将所有内容回滚。节省您很多时间。 –

+0

感谢您的建议。实际上,使用框架是最好的选择。 –

回答

0

感谢您的建议。实际上,使用框架是最好的选择。

相关问题