2017-04-11 5 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クラスは、ドメインやインフラ豆の宣言を含みます。

このクラスは、src/test/javaであり、datasource.propertiesファイルは、テスト.sqlと共にsrc/test/resourcesです。テストクラスは完全に実行され、テストスクリプトが実行され、テーブルが作成されますが、テスト中にリポジトリがデータを検索すると、HSQLDBではなくMySQLが検索されます。ここではテストクラスです:

@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()); 
    } 

} 

私は唯一のテスト・データベースに存在していたとMySQL値が200のステータスを得て、一方、403のステータスを持ったユーザ名とパスワードを使用したとき、私はこれを検証しました。 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にDB依存性:

<!-- 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を作成し、BD 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

感謝。実際にフレームワークを使って作業するのが最善の選択肢です。

関連する問題