はじめに
MockMvc を使ったテストプログラムの勉強のためサンプル作りに励んでいましたが、うまく動作せず。エラーの内容を確認しながら試行錯誤するも解決できず。
Spring の Getting Started の記事を見つけて、自分のサンプルと比べてみると、JUnit のバージョンに差異があることに気づく。
紹介されているプログラムは JUnit4 で作成されていた。JUnit5 でMockMvc を利用するには他に必要なことがあるらしい。
このサンプルをJUnit5で動かすことに成功したので紹介します。
利用したプログラム
Eclipseでサンプルを取得。gs-testing-web-complete から以下のファイルだけ gs-testing-web-initial 利用。
- src/main/java/Application.java
- src/main/java/HomeController.java
- src/test/java/WebLayerTest.java
pom.xml の修正
Junit5を利用するため以下をdependenciesに追加。
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-api</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
テストプログラムのJUnit5化
①アノテーション変更
// 変更前
@RunWith(SpringRunner.class)
// 変更後
@ExtendWith(SpringExtension.class)
②インポート文の置き換え
アノテーション @Test をJUnit5 に変更するため import 文を全部削除して、Eclipseのショートカットを使って置き換え。
③テストコンフィグファイルの作成
これが重要でした。個々のテストクラスで、コンポーネントスキャンしてクラスを参照できるようにしてあげます。
以下に、編集後のプログラムを残します。
修正後のJavaプログラム
- src/main/java/hello/Appliation.java (修正なし)
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- src/main/java/hello/HomeController.java(変更なし)
package hello;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HomeController {
@RequestMapping("/")
public @ResponseBody String greeting() {
return "Hello World";
}
}
- src/test/java/hello/WebLayerTest.java
package hello;
import static org.hamcrest.CoreMatchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
@ExtendWith(SpringExtension.class)
@WebMvcTest(HomeController.class)
//tag::test[]
public class WebLayerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello World")));
}
}
//end::test[]
- src/test/java/hello/TestConfig.java
package hello;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({"hello"})
public class TestConfig {
}