以下のコントローラをテストしている。
@Controller
public class MasterController {
@GetMapping("/")
public String goLoginPage(){
return "index";
}
}
この]1 Spring のドキュメントに従って、コントローラをテストしています。
さて、ドキュメントにあるように、Springコンテキスト全体ではなく、ウェブレイヤーだけをインスタンス化して、コントローラをテストしたいと思います。以下はそのためのコードです。
@RunWith(SpringRunner.class)
@WebMvcTest
public class MasterControllerTestWithWebLayer {
@Autowired
MockMvc mockMvc;
@Autowired
MasterController masterController;
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testLoginHome() throws Exception{
mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(view().name("index"));
}
}
このテストを実行すると、Unable to find @SpringBootConfiguration,...etc
というエラーが表示されます。しかし、Springをインスタンス化するのではなく、Webレイヤーのみを使用したいのに、なぜSpringのコンフィギュレーションを要求するのか混乱しています。ここで何が起こっているのか、正しい方向を教えてください。また、これを修正する方法も教えてください。ありがとうございます。
そこで解決策だ:
テスト構成の検出に関する文書]1には次のように書かれています:
検索アルゴリズムは、@SpringBootApplication または @SpringBootConfiguration アノテーションクラスを見つけるまで、テストを含むパッケージから順に検索します。コードを理にかなった方法で構成している限り、メインのコンフィギュレーションはたいてい見つかります。
たとえば、テストクラスが com.zerosolutions.controller
パッケージにある場合は、@SpringBootApplication
クラスは com.zerosolutions.controller
パッケージよりも上位のパッケージ、つまり com.zerosolutions
や com
にあるはずです。
**問題
しかし、@SpringBootApplication
クラスが test クラスと同じ階層にある場合、com.zerosolutions.general
を見つけることができません。この場合、次のようなエラーが発生します:
java.lang.IllegalStateException:SpringBootConfigurationが見つかりません。テストで@ContextConfigurationまたは@SpringBootTest(classes=...)を使用する必要があります。
**解決方法
統合テストを実行する場合は、次のように @SpringBootApplication
クラスを明示的に指定します。
@RunWith(SpringRunner.class)
@SpringBootTest(classes={SpringBootApp.class})
しかし、コントローラの単体テストを行う場合は、Springコンテキスト全体を起動する必要はありません。SpringBootTestを
@WebMvcTest(MasterController.class)に置き換えることができる。これで、Spring コンテキスト全体ではなく、Web レイヤーの
MasterController` だけをインスタンス化することができる。
**問題
しかし、問題は先ほど直面したエラーに再び遭遇することだ: java.lang.IllegalStateException:SpringBootConfigurationが見つからないので、@ContextConfigurationか@SpringBootTest(classes=...)をテストに使う必要があります。
そして、@WebMvtTest
には @SpringBootTest
のように @SpringBootApplication
クラスを明示的に指定する classes
属性がありません。
そのため、解決策は2つあります。
**解決方法
**1つ目アプリケーションクラスをテストクラスより上位のパッケージ、つまり com.zerosolutions
または com
パッケージに移動します。
**2つ目次のように @SpringBootApplication
クラスを明示的に指定します。
@RunWith(SpringRunner.class)
@WebMvcTest(MasterController.class)
@ContextConfiguration(classes={SpringBootApp.class})
これでSpring Test Configurationの混乱が解消されると思います。ありがとうございます。
Application.javaクラス(src/main/javaにある)が
com.A.B`の下にある場合
テストクラスApplicationTest.java(src/test/javaにある)は、com.A.B
の下にある必要があります。
com.A.Bまたは
com.A.B.Cまたは
com.A.B.C.D` の下にある必要がある。
テストクラスが以下のパッケージの下にある場合、このエラーが発生します。
com.A
または com.A.C
または com.A.D
のいずれかである。
Spring bootでは 一般的なルールは、テストクラスのパッケージ名は、テストされるJavaクラスのパッケージ名で始まる必要がある です。
プロジェクトを生成したときに、pom.xmlのgroupIdが実際のドメインではなく、com.exampleと表示されていました:
groupId>com.exampleです。 pom.xmlを修正した: groupId>com.mydomain</groupId>
」と修正した。
次に、ファイル構造を次のように変更した:
次に、ファイル構造を src/test/java/com/example
から src/test/java/com/mydomain
に変更した。
最後に、src/test/java/com/mydomain
の中のパッケージ宣言を更新しなければならなかった。
の中のパッケージ宣言を更新しなければならなかった。
ファイル内のパッケージ宣言を更新しなければならなかった。これがすべて整うと、テストはうまくいった。
プロジェクトの他の部分は正しいのに、どうしてcom.exampleになってしまったのかはわからない。
どなたかのお役に立てれば幸いです。