spring-boot
スタータークラスが標準のように見える@SpringBootApplication
アプリケーションがあります。そのため、すべての機能について多くのテストを作成し、概要を sonarqube に送信して、カバレッジを確認しました。
私のスタータークラスについて、Sonarqubeは、私は60%のカバレッジしかないことを教えてくれます。そのため、平均的なカバレッジは期待どおりではありません。
私のテストクラスはデフォルトです。
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElectronicGiftcardServiceApplication.class)
public class ElectronicGiftcardServiceApplicationTests {
@Test
public void contextLoads() {
}
}
では、アプリケーションのスタータークラスでメインクラスをテストするにはどうすればよいですか?
これらの答えはすべてやり過ぎのようです。
メトリックツールを満足させるためのテストを追加しないでください。
アプリケーションのSpringコンテキストの読み込みには時間がかかります。アプリケーションのカバレッジの約0.1%を獲得するためだけに、各開発者ビルドに追加しないでください。
ここ1つのパブリックメソッドから1つのステートメントだけをカバーするわけではありません。通常、数千のステートメントが記述されているアプリケーションのカバレッジに関しては何も表していません。
最初の回避策:内部で宣言されたBeanのないSpring Bootアプリケーションクラスを作成します。それらがある場合は、それらを構成クラスに移動します(ユニットテストでカバーできるようにします)。そして、 テストカバレッジ設定でSpring Bootアプリケーションクラスを無視します。
2番目の回避策:main()
呼び出し(組織上の理由など)をカバーする必要がある場合は、テストを作成しますが、統合テスト(各開発者ビルドではなく、継続的統合ツールによって実行)とドキュメントを作成します明確にテストクラスの目的:
import org.junit.Test;
// Test class added ONLY to cover main() invocation not covered by application tests.
public class MyApplicationIT {
@Test
public void main() {
MyApplication.main(new String[] {});
}
}
このようなことができます
@Test
public void applicationContextLoaded() {
}
@Test
public void applicationContextTest() {
mainApp.main(new String[] {});
}
私は同じ目標を持っていて(main()メソッドを実行するテストを持っています)、@ fg78ncのようなテストメソッドを追加するだけで、実際にアプリケーションを2回「開始」することに気付きました:1回はスプリングブートテストフレームワークによって、1回はmainApp.main(new String[] {})
の明示的な呼び出し。これはエレガントではありません。
私は2つのテストクラスを書いた:1つは@SpringBootTest
アノテーションと空のテストメソッドapplicationContextLoaded()、もう1つは@SpringBootTest
なし(RunWith(SpringRunner.class)
のみ) )mainメソッドを呼び出します。
SpringBootApplicationTest
package example;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.boot.test.context.SpringBootTest;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootApplicationTest {
@Test
public void contextLoads() {
}
}
ApplicationStartTest
package example;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
public class ApplicationStartTest {
@Test
public void applicationStarts() {
ExampleApplication.main(new String[] {});
}
}
全体として、アプリケーションはまだ2回起動されますが、2つのテストクラスが存在するためです。もちろん、これらの2つのテストメソッドだけでは過剰に思えますが、通常、@SpringBootTest
セットアップを利用して、クラスSpringBootApplicationTest
に追加のテストが追加されます。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>your.awesome.package.Application</mainClass>
</configuration>
</plugin>
100%のカバレッジを目指す場合、できることの1つは、単にメインメソッドをまったく持たないことです。 @SpringBootApplication
アノテーションが付けられたクラスが必要ですが、空にすることもできます。
ただし、欠点があり、main
に依存する他のツールが破損する可能性があるため、注意してください。
SpringApplication
は、テスト対象のメソッドの依存関係であるため、モックできます。 こちら をご覧ください。つまり.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.boot.SpringApplication;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
@RunWith(PowerMockRunner.class)
public class ElectronicGiftcardServiceApplicationTest {
@Test
@PrepareForTest(SpringApplication.class)
public void main() {
mockStatic(SpringApplication.class);
ElectronicGiftcardServiceApplication.main(new String[]{"Hello", "World"});
verifyStatic(SpringApplication.class);
SpringApplication.run(ElectronicGiftcardServiceApplication.class, new String[]{"Hello", "World"});
}
}