Spring Boot + npm + Geb で入力フォームを作ってテストする ( その63 )( MockMvc#perform 呼び出し時に .with(csrf()) を付けていなくてもテストが成功していた理由とは? )
概要
記事一覧はこちらです。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その62 )( 確認画面を作成する5 ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- 確認画面のテストを作成し終えた時に、今回 Spring Security を入れて CSRF対策も入っているはずなのに MockMvc#perform 呼び出し時に
.with(csrf())
を付けていないのにテストが成功しているというおかしな事態になっていることに気づいたので、その原因を調査します。
- 確認画面のテストを作成し終えた時に、今回 Spring Security を入れて CSRF対策も入っているはずなのに MockMvc#perform 呼び出し時に
参照したサイト・書籍
- Spring Security Reference - 12. Spring MVC Test Integration
https://docs.spring.io/spring-security/site/docs/current/reference/html/test-mockmvc.html
目次
- 単に
.apply(springSecurity())
を付け忘れいてただけでした。。。 - InquiryInputControllerTest クラスを修正する
- InquiryConfirmControllerTest クラスを修正する
手順
単に .apply(springSecurity())
を付け忘れいてただけでした。。。
Spring Security Reference - 12. Spring MVC Test Integration を見たら1発で原因が分かりました。単なる .apply(springSecurity())
の付け忘れでした。。。
ということで、入力画面・確認画面のテストで MockMvc のインスタンス生成時に .apply(springSecurity())
を付けるよう修正して、テストを見直すことにします。
InquiryInputControllerTest クラスを修正する
最初に MockMvc のインスタンス生成時に .apply(springSecurity())
を付けるよう修正します。
@Before
void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(springSecurity())
.build()
}
全てのテストを実行すると、今度は 403 のエラーが出るようになりました。
テスト内で POST でリクエストを送信しているところを TestHelper.postForm(...)
→ TestHelper.postForm(...).with(csrf())
のように修正します。
再度全てのテストを実行すると、テストを実装していない(必ず失敗する)1件を除き成功しました。
InquiryConfirmControllerTest クラスを修正する
こちらも MockMvc のインスタンス生成時に .apply(springSecurity())
を付けるよう修正します。意識していませんでしたが、InquiryInputControllerTest は JUnit4+Groovy で書いていますが、InquiryConfirmControllerTest は Spock+Groovy で書いていました。
def setup() { mockMvc = MockMvcBuilders.webAppContextSetup(context) .apply(springSecurity()) .build() sql = new Sql(dataSource) sql.execute("truncate table INQUIRY_DATA") }
全てのテストを実行すると、こちらも 403 のエラーが出るようになりました。
テスト内で POST でリクエストを送信しているところを TestHelper.postForm(...)
→ TestHelper.postForm(...).with(csrf())
のように修正します。
再度全てのテストを実行すると、今度は成功しました。
最後に修正後のソースコードを載せておきます。
ソースコード
InquiryInputControllerTest.groovy
package ksbysample.webapp.bootnpmgeb.web.inquiry import ksbysample.common.test.helper.TestHelper import ksbysample.webapp.bootnpmgeb.values.Type1Values import ksbysample.webapp.bootnpmgeb.values.Type2Values import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput01Form import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput02Form import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput03Form import org.junit.Before import org.junit.Test import org.junit.experimental.runners.Enclosed import org.junit.runner.RunWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.mock.web.MockHttpSession import org.springframework.test.context.junit4.SpringRunner import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.MvcResult import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.web.context.WebApplicationContext import org.yaml.snakeyaml.Yaml import static ksbysample.common.test.matcher.HtmlResultMatchers.html import static org.assertj.core.api.Assertions.catchThrowable import static org.assertj.core.api.AssertionsForClassTypes.assertThat import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @RunWith(Enclosed) class InquiryInputControllerTest { @RunWith(SpringRunner) @SpringBootTest static class 入力画面1のテスト { private InquiryInput01Form inquiryInput01Form_001 = (InquiryInput01Form) new Yaml().load(getClass().getResourceAsStream("InquiryInput01Form_001.yaml")) @Autowired private WebApplicationContext context MockMvc mockMvc @Before void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(context) .apply(springSecurity()) .build() } @Test void "初期表示時は画面の項目には何もセットされない"() { expect: mockMvc.perform(get("/inquiry/input/01")) .andExpect(status().isOk()) .andExpect(html("#lastname").val("")) .andExpect(html("#firstname").val("")) .andExpect(html("#lastkana").val("")) .andExpect(html("#firstkana").val("")) .andExpect(html("input[name='sex'][checked='checked']").notExists()) .andExpect(html("#age").val("")) .andExpect(html("select[name='job'] option[selected]").notExists()) } @Test void "項目全てに入力して入力画面2へ遷移してから戻ると以前入力したデータがセットされて表示される"() { expect: "項目全てに入力して「次へ」ボタンをクリックする" MvcResult result = mockMvc.perform( TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf())) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) .andReturn() MockHttpSession session = result.getRequest().getSession() and: "再び入力画面1を表示する" mockMvc.perform(get("/inquiry/input/01").session(session)) .andExpect(status().isOk()) .andExpect(html("#lastname").val(inquiryInput01Form_001.lastname)) .andExpect(html("#firstname").val(inquiryInput01Form_001.firstname)) .andExpect(html("#lastkana").val(inquiryInput01Form_001.lastkana)) .andExpect(html("#firstkana").val(inquiryInput01Form_001.firstkana)) .andExpect(html("input[name='sex'][checked='checked']").val(inquiryInput01Form_001.sex)) .andExpect(html("#age").val(inquiryInput01Form_001.age)) .andExpect(html("select[name='job'] option[selected]").val(inquiryInput01Form_001.job)) } @Test void "入力チェックエラーのあるデータで入力画面2へ遷移しようとするとIllegalArgumentExceptionが発生する"() { setup: "入力チェックエラーになるデータを用意する" inquiryInput01Form_001.lastname = "x" * 21 expect: "入力画面1の「次へ」ボタンをクリックする" Throwable thrown = catchThrowable({ mockMvc.perform( TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf())) .andExpect(status().isOk()) }) assertThat(thrown.cause).isInstanceOf(IllegalArgumentException) } } @RunWith(SpringRunner) @SpringBootTest static class 入力画面2のテスト { private InquiryInput01Form inquiryInput01Form_001 = (InquiryInput01Form) new Yaml().load(getClass().getResourceAsStream("InquiryInput01Form_001.yaml")) private InquiryInput02Form inquiryInput02Form_001 = new InquiryInput02Form( zipcode1: "102" , zipcode2: "0072" , address: "東京都千代田区飯田橋1-1" , tel1: "03" , tel2: "1234" , tel3: "5678" , email: "taro.tanaka@sample.co.jp") @Autowired private WebApplicationContext context MockMvc mockMvc @Before void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(context) .build() } @Test void "初期表示時は画面の項目には何もセットされない"() { expect: mockMvc.perform(get("/inquiry/input/02")) .andExpect(status().isOk()) .andExpect(html("#zipcode1").val("")) .andExpect(html("#zipcode2").val("")) .andExpect(html("#address").val("")) .andExpect(html("#tel1").val("")) .andExpect(html("#tel2").val("")) .andExpect(html("#tel3").val("")) .andExpect(html("#email").val("")) } @Test void "項目全てに入力して前の画面へ戻るボタンをクリックすると入力画面1へ戻り、次へ戻るボタンを押して入力画面2へ戻ると以前入力したデータがセットされて表示される"() { when: "入力画面1で項目全てに入力して「次へ」ボタンをクリックする" MvcResult result = mockMvc.perform( TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf())) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) .andReturn() MockHttpSession session = result.getRequest().getSession() and: "入力画面2で項目全てに入力して「前の画面へ戻る」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=back", inquiryInput02Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/01")) and: "入力画面1で「次へ」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) then: "入力画面2が以前入力したデータがセットされて表示される" mockMvc.perform(get("/inquiry/input/02").session(session)) .andExpect(status().isOk()) .andExpect(html("#zipcode1").val(inquiryInput02Form_001.zipcode1)) .andExpect(html("#zipcode2").val(inquiryInput02Form_001.zipcode2)) .andExpect(html("#address").val(inquiryInput02Form_001.address)) .andExpect(html("#tel1").val(inquiryInput02Form_001.tel1)) .andExpect(html("#tel2").val(inquiryInput02Form_001.tel2)) .andExpect(html("#tel3").val(inquiryInput02Form_001.tel3)) .andExpect(html("#email").val(inquiryInput02Form_001.email)) } @Test void "項目全てに入力して次へボタンをクリックすると入力画面3へ遷移し、前の画面へ戻るボタンを押して入力画面2へ戻ると以前入力したデータがセットされて表示される"() { when: "入力画面2で項目全てに入力して「次へ」ボタンをクリックする" MvcResult result = mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf())) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/03")) .andReturn() MockHttpSession session = result.getRequest().getSession() and: "入力画面3で「前の画面へ戻る」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/03?move=back", inquiryInput01Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) then: "入力画面2が以前入力したデータがセットされて表示される" mockMvc.perform(get("/inquiry/input/02").session(session)) .andExpect(status().isOk()) .andExpect(html("#zipcode1").val(inquiryInput02Form_001.zipcode1)) .andExpect(html("#zipcode2").val(inquiryInput02Form_001.zipcode2)) .andExpect(html("#address").val(inquiryInput02Form_001.address)) .andExpect(html("#tel1").val(inquiryInput02Form_001.tel1)) .andExpect(html("#tel2").val(inquiryInput02Form_001.tel2)) .andExpect(html("#tel3").val(inquiryInput02Form_001.tel3)) .andExpect(html("#email").val(inquiryInput02Form_001.email)) } @Test void "入力チェックエラーのあるデータで「前の画面へ戻る」ボタンをクリックするとIllegalArgumentExceptionが発生する"() { setup: "入力チェックエラーになるデータを用意する" inquiryInput02Form_001.zipcode1 = "1" expect: "入力画面2の「前の画面へ戻る」ボタンをクリックする" Throwable thrown = catchThrowable({ mockMvc.perform( TestHelper.postForm("/inquiry/input/02?move=back", inquiryInput02Form_001).with(csrf())) .andExpect(status().isOk()) }) assertThat(thrown.cause).isInstanceOf(IllegalArgumentException) } @Test void "入力チェックエラーのあるデータで「次へ」ボタンをクリックするとIllegalArgumentExceptionが発生する"() { setup: "入力チェックエラーになるデータを用意する" inquiryInput02Form_001.zipcode1 = "1" expect: "入力画面2の「次へ」ボタンをクリックする" Throwable thrown = catchThrowable({ mockMvc.perform( TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf())) .andExpect(status().isOk()) }) assertThat(thrown.cause).isInstanceOf(IllegalArgumentException) } } @RunWith(SpringRunner) @SpringBootTest static class 入力画面3のテスト { private InquiryInput01Form inquiryInput01Form_001 = (InquiryInput01Form) new Yaml().load(getClass().getResourceAsStream("InquiryInput01Form_001.yaml")) private InquiryInput02Form inquiryInput02Form_001 = new InquiryInput02Form( zipcode1: "102" , zipcode2: "0072" , address: "東京都千代田区飯田橋1-1" , tel1: "03" , tel2: "1234" , tel3: "5678" , email: "taro.tanaka@sample.co.jp") private InquiryInput03Form inquiryInput03Form_001 = new InquiryInput03Form( type1: Type1Values.PRODUCT.value , type2: [Type2Values.ESTIMATE.value, Type2Values.CATALOGUE.value, Type2Values.OTHER.value] , inquiry: "これはテストです" , survey: ["1", "2", "3", "4", "5", "6", "7", "8"]) @Autowired private WebApplicationContext context MockMvc mockMvc @Before void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(context) .build() } @Test void "初期表示時は画面の項目には何もセットされない"() { expect: mockMvc.perform(get("/inquiry/input/03")) .andExpect(status().isOk()) .andExpect(html("select[name='type1'] option[selected]").notExists()) .andExpect(html("input[name='type2'][checked='checked']").notExists()) .andExpect(html("#inquiry").val("")) .andExpect(html("input[name='survey'][checked='checked']").notExists()) } @Test void "項目全てに入力して前の画面へ戻るボタンをクリックすると入力画面2へ戻り、次へ戻るボタンを押して入力画面3へ戻ると以前入力したデータがセットされて表示される"() { when: "入力画面1で項目全てに入力して「次へ」ボタンをクリックする" MvcResult result = mockMvc.perform( TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf())) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) .andReturn() MockHttpSession session = result.getRequest().getSession() and: "入力画面2で項目全てに入力して「次へ」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/03")) and: "入力画面3で項目全てに入力して「前の画面へ戻る」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/03?move=back", inquiryInput03Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) and: "入力画面2で「次へ」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/03")) then: "入力画面3が以前入力したデータがセットされて表示される" mockMvc.perform(get("/inquiry/input/03").session(session)) .andExpect(status().isOk()) .andExpect(html("select[name='type1'] option[selected]").val(inquiryInput03Form_001.type1)) .andExpect(html("input[name='type2'][checked='checked']").count(3)) .andExpect(html("#inquiry").val(inquiryInput03Form_001.inquiry)) .andExpect(html("input[name='survey'][checked='checked']").count(8)) } @Test void "項目全てに入力して次へボタンをクリックすると確認画面へ遷移し、前の画面へ戻るボタンを押して入力画面3へ戻ると以前入力したデータがセットされて表示される"() { expect: assert false, "確認画面を実装してからテストを作成する" } @Test void "入力チェックエラーのあるデータで「次へ」ボタンをクリックするとIllegalArgumentExceptionが発生する"() { setup: "入力チェックエラーになるデータを用意する" inquiryInput03Form_001.type1 = "" expect: "入力画面3の「次へ」ボタンをクリックする" Throwable thrown = catchThrowable({ mockMvc.perform( TestHelper.postForm("/inquiry/input/03?move=next", inquiryInput03Form_001).with(csrf())) .andExpect(status().isOk()) }) assertThat(thrown.cause).isInstanceOf(IllegalArgumentException) } } }
InquiryConfirmControllerTest.groovy
package ksbysample.webapp.bootnpmgeb.web.inquiry import groovy.sql.Sql import ksbysample.common.test.helper.TestHelper import ksbysample.common.test.rule.mail.MailServerResource import ksbysample.webapp.bootnpmgeb.dao.InquiryDataDao import ksbysample.webapp.bootnpmgeb.entity.SurveyOptions import ksbysample.webapp.bootnpmgeb.helper.db.SurveyOptionsHelper import ksbysample.webapp.bootnpmgeb.values.* import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput01Form import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput02Form import ksbysample.webapp.bootnpmgeb.web.inquiry.form.InquiryInput03Form import org.apache.commons.lang3.StringUtils import org.junit.Rule import org.junit.experimental.runners.Enclosed import org.junit.runner.RunWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.core.io.ClassPathResource import org.springframework.http.MediaType import org.springframework.mock.web.MockHttpSession import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.MvcResult import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.web.context.WebApplicationContext import org.yaml.snakeyaml.Yaml import spock.lang.Specification import javax.mail.internet.MimeMessage import javax.sql.DataSource import java.util.stream.Collectors import static ksbysample.common.test.matcher.HtmlResultMatchers.html import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @RunWith(Enclosed) class InquiryConfirmControllerTest { @SpringBootTest static class 確認画面のテスト extends Specification { InquiryInput01Form inquiryInput01Form_001 = (InquiryInput01Form) new Yaml().load(getClass().getResourceAsStream("InquiryInput01Form_001.yaml")) InquiryInput02Form inquiryInput02Form_001 = new InquiryInput02Form( zipcode1: "102" , zipcode2: "0072" , address: "東京都千代田区飯田橋1-1" , tel1: "03" , tel2: "1234" , tel3: "5678" , email: "taro.tanaka@sample.co.jp") InquiryInput03Form inquiryInput03Form_001 = new InquiryInput03Form( type1: Type1Values.PRODUCT.value , type2: [Type2Values.ESTIMATE.value, Type2Values.CATALOGUE.value, Type2Values.OTHER.value] , inquiry: "これはテストです" , survey: ["1", "2", "3", "4", "5", "6", "7", "8"]) @Rule MailServerResource mailServerResource = new MailServerResource() @Autowired WebApplicationContext context @Autowired DataSource dataSource @Autowired ValuesHelper vh @Autowired SurveyOptionsHelper soh @Autowired InquiryDataDao inquiryDataDao MockMvc mockMvc Sql sql def setup() { mockMvc = MockMvcBuilders.webAppContextSetup(context) .apply(springSecurity()) .build() sql = new Sql(dataSource) sql.execute("truncate table INQUIRY_DATA") } def teardown() { sql.close() } def "入力画面1~3で全ての項目に入力した場合のテスト"() { when: "入力画面1で項目全てに入力して「次へ」ボタンをクリックする" MvcResult result = mockMvc.perform(TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf())) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) .andReturn() MockHttpSession session = result.getRequest().getSession() and: "入力画面2で項目全てに入力して「次へ」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/03")) and: "入力画面3で項目全てに入力して「次へ」ボタンをクリックする" mockMvc.perform(TestHelper.postForm("/inquiry/input/03?move=next", inquiryInput03Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/confirm")) then: "確認画面に入力画面1~3で入力したデータが表示される" mockMvc.perform(get("/inquiry/confirm").session(session)) .andExpect(status().isOk()) .andExpect(html("#name").text(inquiryInput01Form_001.lastname + " " + inquiryInput01Form_001.firstname)) .andExpect(html("#kana").text(inquiryInput01Form_001.lastkana + " " + inquiryInput01Form_001.firstkana)) .andExpect(html("#sex").text(vh.getText(SexValues, inquiryInput01Form_001.sex))) .andExpect(html("#age").text(inquiryInput01Form_001.age + " 歳")) .andExpect(html("#job").text(vh.getText(JobValues, inquiryInput01Form_001.job))) .andExpect(html("#zipcode").text("〒 " + inquiryInput02Form_001.zipcode1 + "-" + inquiryInput02Form_001.zipcode2)) .andExpect(html("#address").text(inquiryInput02Form_001.address)) .andExpect(html("#tel").text(inquiryInput02Form_001.tel1 + "-" + inquiryInput02Form_001.tel2 + "-" + inquiryInput02Form_001.tel3)) .andExpect(html("#email").text(inquiryInput02Form_001.email)) .andExpect(html("#type1").text(vh.getText(Type1Values, inquiryInput03Form_001.type1))) .andExpect(html("#type2").text([Type2Values.ESTIMATE.text , Type2Values.CATALOGUE.text , Type2Values.OTHER.text].stream().collect(Collectors.joining("、")))) .andExpect(html("#inquiry").text(inquiryInput03Form_001.inquiry)) .andExpect(html("#survey > ul > li").count(8)) .andExpect(html("#survey > ul > li:nth-of-type(1)").text( soh.selectItemList("survey").stream() .filter({ SurveyOptions surveyOptions -> StringUtils.equals(surveyOptions.itemValue, "1") }) .map { SurveyOptions surveyOptions -> surveyOptions.itemName } .findFirst().get())) and: "確認画面で「送信」ボタンをクリックする" mockMvc.perform(post("/inquiry/confirm/send").contentType(MediaType.APPLICATION_FORM_URLENCODED).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/complete/")) then: "DBとメールを確認する" def rows = sql.rows("SELECT * FROM INQUIRY_DATA") rows.size() == 1 rows[0]["lastname"] == "12345678901234567890" rows[0]["firstname"] == "12345678901234567890" rows[0]["lastkana"] == "あいうえおかきくけこさしすせそたちつてと" rows[0]["firstkana"] == "なにぬねのはひふへほまみむめもあいうえお" rows[0]["sex"] == "2" rows[0]["age"] == 999 rows[0]["job"] == "3" rows[0]["zipcode1"] == "102" rows[0]["zipcode2"] == "0072" rows[0]["address"] == "東京都千代田区飯田橋1-1" rows[0]["tel1"] == "03" rows[0]["tel2"] == "1234" rows[0]["tel3"] == "5678" rows[0]["email"] == "taro.tanaka@sample.co.jp" rows[0]["type1"] == "1" rows[0]["type2"] == "1,2,3" rows[0]["inquiry"].asciiStream.text == inquiryInput03Form_001.inquiry rows[0]["survey"] == "1,2,3,4,5,6,7,8" mailServerResource.messagesCount == 1 MimeMessage message = mailServerResource.firstMessage message.subject == "問い合わせフォームからお問い合わせがありました" message.content == new ClassPathResource("ksbysample/webapp/bootnpmgeb/web/inquiry/inquirymail-body_001.txt").inputStream.text } def "入力画面1~3で必須項目だけに入力した場合のテスト"() { when: "入力画面1で必須項目だけに入力して「次へ」ボタンをクリックする" inquiryInput01Form_001.job = StringUtils.EMPTY MvcResult result = mockMvc.perform(TestHelper.postForm("/inquiry/input/01?move=next", inquiryInput01Form_001).with(csrf())) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/02")) .andReturn() MockHttpSession session = result.getRequest().getSession() and: "入力画面2で必須項目だけに入力して「次へ」ボタンをクリックする" inquiryInput02Form_001.tel1 = StringUtils.EMPTY inquiryInput02Form_001.tel2 = StringUtils.EMPTY inquiryInput02Form_001.tel3 = StringUtils.EMPTY mockMvc.perform(TestHelper.postForm("/inquiry/input/02?move=next", inquiryInput02Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/input/03")) and: "入力画面3で必須項目だけに入力して「次へ」ボタンをクリックする" inquiryInput03Form_001.survey = [] mockMvc.perform(TestHelper.postForm("/inquiry/input/03?move=next", inquiryInput03Form_001).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/confirm")) then: "確認画面に入力画面1~3で入力したデータが表示される" mockMvc.perform(get("/inquiry/confirm").session(session)) .andExpect(status().isOk()) .andExpect(html("#name").text(inquiryInput01Form_001.lastname + " " + inquiryInput01Form_001.firstname)) .andExpect(html("#kana").text(inquiryInput01Form_001.lastkana + " " + inquiryInput01Form_001.firstkana)) .andExpect(html("#sex").text(vh.getText(SexValues, inquiryInput01Form_001.sex))) .andExpect(html("#age").text(inquiryInput01Form_001.age + " 歳")) .andExpect(html("#job").text(StringUtils.EMPTY)) .andExpect(html("#zipcode").text("〒 " + inquiryInput02Form_001.zipcode1 + "-" + inquiryInput02Form_001.zipcode2)) .andExpect(html("#address").text(inquiryInput02Form_001.address)) .andExpect(html("#tel").text(StringUtils.EMPTY)) .andExpect(html("#email").text(inquiryInput02Form_001.email)) .andExpect(html("#type1").text(vh.getText(Type1Values, inquiryInput03Form_001.type1))) .andExpect(html("#type2").text([Type2Values.ESTIMATE.text , Type2Values.CATALOGUE.text , Type2Values.OTHER.text].stream().collect(Collectors.joining("、")))) .andExpect(html("#inquiry").text(inquiryInput03Form_001.inquiry)) .andExpect(html("#survey > ul > li").count(0)) and: "確認画面で「送信」ボタンをクリックする" mockMvc.perform(post("/inquiry/confirm/send").contentType(MediaType.APPLICATION_FORM_URLENCODED).with(csrf()).session(session)) .andExpect(status().isFound()) .andExpect(redirectedUrlPattern("**/inquiry/complete/")) then: "DBとメールを確認する" def rows = sql.rows("SELECT * FROM INQUIRY_DATA") rows.size() == 1 rows[0]["lastname"] == "12345678901234567890" rows[0]["firstname"] == "12345678901234567890" rows[0]["lastkana"] == "あいうえおかきくけこさしすせそたちつてと" rows[0]["firstkana"] == "なにぬねのはひふへほまみむめもあいうえお" rows[0]["sex"] == "2" rows[0]["age"] == 999 rows[0]["job"] == StringUtils.EMPTY rows[0]["zipcode1"] == "102" rows[0]["zipcode2"] == "0072" rows[0]["address"] == "東京都千代田区飯田橋1-1" rows[0]["tel1"] == StringUtils.EMPTY rows[0]["tel2"] == StringUtils.EMPTY rows[0]["tel3"] == StringUtils.EMPTY rows[0]["email"] == "taro.tanaka@sample.co.jp" rows[0]["type1"] == "1" rows[0]["type2"] == "1,2,3" rows[0]["inquiry"].asciiStream.text == inquiryInput03Form_001.inquiry rows[0]["survey"] == StringUtils.EMPTY mailServerResource.messagesCount == 1 MimeMessage message = mailServerResource.firstMessage message.subject == "問い合わせフォームからお問い合わせがありました" message.content == new ClassPathResource("ksbysample/webapp/bootnpmgeb/web/inquiry/inquirymail-body_002.txt").inputStream.text } } }
履歴
2018/07/08
初版発行。