Maven、JUnit、およびSpringによる統合テスト

単体テストは良いことですが、私の意見では、単体テストだけに頼ることはできません。 複数のクラスがどのように機能するかを確認することが非常に重要な場合があります。また、アプリケーション層が一緒になっている場合もあります。

私たちのアプリケーションはSpringを積極的に使用しています。つまり、このような統合テストはSpringコンテキストで動作するはずです。

多くの場合、メモリ内データベースを使用していても、このようなテストには時間がかかることがあります(ちなみに、理由を確認しました-それぞれに多くのプロパティを持つJPAエンティティが多数あり、Hibernateの初期化には数十秒かかります!)

そのため、デフォルトでは、これらのテストは、通常の単体テストとは異なり、ビルド中に実行されないようにする必要があります。

したがって、計画は次のとおりです。
1.アプリケーションの2つの層に分割されたサービスを記述します
2.それらをSpringに接続する
3.これらのサービスの相互作用のためにJUnitを使用してテストを作成します(モックなしの実際の)
4.このテストがビルド中にデフォルトで実行されないことを確認してください
5.利益!


1.アプリケーションの2つの層に分割されたサービスを記述します


なぜ2層なのか? コードがスパゲッティにならないように、ビジネスロジックをレイヤー(永続レイヤーなど)に分割することを好みます。 レイヤーには階層があります-誰が誰を呼び出すことができ、レイヤーを異なるMavenプロジェクトに分離することにより、禁止されている依存関係がないことを確認します。

そのため、誰もが必要とする依存関係を持つアプリケーション全体のpom.xmlを作成します。

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany</groupId> <artifactId>myapp</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>myapp</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring-version>3.1.0.RELEASE</spring-version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring-version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency> </dependencies> <modules> <module>backend</module> <module>frontend</module> <module>gui</module> </modules> </project> 


gui、フロントエンド、バックエンド(2層のビジネスロジック)の3つのモジュールがあります。

フロントエンドのpom.xmlは次のとおりです。
 <?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.mycompany</groupId> <artifactId>myapp</artifactId> <version>1.0-SNAPSHOT</version> </parent> <groupId>com.mycompany</groupId> <artifactId>frontend</artifactId> <version>1.0-SNAPSHOT</version> <name>frontend</name> <dependencies> <dependency> <groupId>com.mycompany</groupId> <artifactId>backend</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project> 


ご覧のとおり、それはバックエンドに依存し、父親のポンから他のすべてを受け取ります。

バックエンドのpom.xmlは次のとおりです。

 <?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.mycompany</groupId> <artifactId>myapp</artifactId> <version>1.0-SNAPSHOT</version> </parent> <groupId>com.mycompany</groupId> <artifactId>backend</artifactId> <version>1.0-SNAPSHOT</version> <name>backend</name> </project> 


ディレクトリbackend / src / main / java / com / mycompany / service / backendで、次を作成します。

IBackendService1.java:
 package com.mycompany.service.backend; public interface IBackendService1 { String computeSecretString(); } 


IBackendService2.java:

 package com.mycompany.service.backend; public interface IBackendService2 { int computeSecretNumber(); } 


BackendService1.java:

 package com.mycompany.service.backend; public class BackendService1 implements IBackendService1 { @Override public String computeSecretString() { return "James Bond"; } } 


BackendService2.java:

 package com.mycompany.service.backend; public class BackendService2 implements IBackendService2 { @Override public int computeSecretNumber() { return 7; } } 


ディレクトリfrontend / src / main / java / com / mycompany / service / frontendで、次を作成します。

IFrontendService.java:

 package com.mycompany.service.frontend; public interface IFrontendService { String getAgent(); } 


FrontendService.java:

 package com.mycompany.service.frontend; import com.mycompany.service.backend.*; public class FrontendService implements IFrontendService { private IBackendService1 backendService1; private IBackendService2 backendService2; public FrontendService(IBackendService1 backendService1, IBackendService2 backendService2) { this.backendService1 = backendService1; this.backendService2 = backendService2; } @Override public String getAgent() { return backendService1.computeSecretString()+backendService2.computeSecretNumber(); } } 


2.それらをSpringに接続する

バックエンド/ src / main / resources / backend-beans.xml:

 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="names_provider" class="com.mycompany.service.backend.BackendService1"/> <bean id="secret_service" class="com.mycompany.service.backend.BackendService2"/> </beans> 


フロントエンド/ src / main / resources / frontend-beans.xml:

 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd "> <import resource="classpath:backend-beans.xml"/> <bean id="agent_service" class="com.mycompany.service.frontend.FrontendService"> <constructor-arg index="0" ref="names_provider"/> <constructor-arg index="1" ref="secret_service"/> </bean> </beans> 


3.これらのサービスの相互作用のためにJUnitを使用してテストを作成します(モックなしの実際の)


ディレクトリフロントエンド/ src / test / java / com / mycompany / integration
FrontendServiceTest.java:

 package com.mycompany.integration; import com.mycompany.service.frontend.IFrontendService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) @ContextConfiguration(locations = {"classpath:frontend-beans.xml"}) public class FrontendServiceTest { @Autowired IFrontendService frontendService; @Test public void testBond() { String agent = frontendService.getAgent(); assertTrue("It should be Bond", agent.contains("Bond")); } } 


注釈に注意してください。
@RunWith(SpringJUnit4ClassRunner.class)の「トリガー」でテストを実行します
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -各テストメソッドに対してスプリングコンテキストを再度作成します
@ContextConfiguration(locations = {"classpath:frontend-beans.xml"}) -Beanを取得する場所

@ActiveProfiles(profiles = "local") -プロファイルを使用する場合。

@Autowired 、Beanをテストクラスに注入します。 特定のインターフェイスを実装するBeanが複数ある場合は、 @Resource(name = "session-operations")置き換えることができます

4.このテストがビルド中にデフォルトで実行されないことを確認してください

アプリケーション全体のpom.xmlに追加します。

  <properties> ... <systest.package>**/com/mycompany/integration/**</systest.package> </properties> <build> .... <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <excludes> <exclude>${systest.package}</exclude> <exclude>**/*$*</exclude> </excludes> </configuration> </plugin> </plugins> </build> 


これで、ビルド中のテストは開始されません。 (内部クラスはテストではないとも言いました)

また、名前だけでなく実行できるように、このexcludeいないプロファイルを追加します。

  <profiles> <profile> <id>systest</id> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.5</version> <configuration> <excludes> <exclude>**/*$*</exclude> </excludes> </configuration> </plugin> </plugins> </build> </profile> </profiles> 


これで、com.mycompany.integrationにあるすべてのテストがビルド中に実行されなくなりますが、実行するには、たとえば次のようにMavenプロファイル「systest」をインストールする必要があります。

mvn -P=systest test

5.利益!

Source: https://habr.com/ru/post/J146984/


All Articles