package sample; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.util.*; import org.hamcrest.Matcher; import org.junit.runner.RunWith; import org.slf4j.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.*; import org.springframework.web.util.*; import sample.context.Timestamper; import sample.model.*; /** * Spring コンテナを用いた Web 検証サポートクラス。 * <p>Controller に対する URL 検証はこちらを利用して下さい。 * <p>本クラスを継承したテストクラスを作成後、以下のアノテーションを付与してください。 * <pre> * {@literal @}RunWith(SpringRunner.class) * {@literal @}WebMvcTest([テスト対象クラス].class) * </pre> * <p>{@literal @}WebMvcTest 利用時は標準で {@literal @}Component や {@literal @}Service 等の * コンポーネントはインスタンス化されないため、必要に応じて {@literal @}MockBean などを利用して代替するようにしてください。 */ @RunWith(SpringRunner.class) @ActiveProfiles("testweb") public abstract class WebTestSupport { protected static final Logger logger = LoggerFactory.getLogger("ControllerTest"); @Autowired protected MockMvc mvc; protected Timestamper mockTime; protected BusinessDayHandler businessDay; protected DataFixtures fixtures; public WebTestSupport() { this.mockTime = new Timestamper(); this.businessDay = new BusinessDayHandler(); this.businessDay.setTime(mockTime); this.fixtures = new DataFixtures(); this.fixtures.setTime(mockTime); this.fixtures.setBusinessDay(businessDay); } protected String uri(String path) { return prefix() + path; } protected UriComponentsBuilder uriBuilder(String path) { return UriComponentsBuilder.fromUriString(uri(path)); } protected String prefix() { return "/"; } /** Get 要求を投げて結果を検証します。 */ protected ResultActions performGet(String path, final JsonExpects expects) { return performGet(uriBuilder(path).build(), expects); } protected ResultActions performGet(UriComponents uri, final JsonExpects expects) { return perform( get(uri.toUriString()).accept(MediaType.APPLICATION_JSON), expects.expects.toArray(new ResultMatcher[0])); } /** Get 要求 ( JSON ) を投げて結果を検証します。 */ protected ResultActions performJsonGet(String path, String content, final JsonExpects expects) { return performJsonGet(uriBuilder(path).build(), content, expects); } protected ResultActions performJsonGet(UriComponents uri, String content, final JsonExpects expects) { return perform( get(uri.toUriString()).contentType(MediaType.APPLICATION_JSON).content(content).accept(MediaType.APPLICATION_JSON), expects.expects.toArray(new ResultMatcher[0])); } /** Post 要求を投げて結果を検証します。 */ protected ResultActions performPost(String path, final JsonExpects expects) { return performPost(uriBuilder(path).build(), expects); } protected ResultActions performPost(UriComponents uri, final JsonExpects expects) { return perform( post(uri.toUriString()).accept(MediaType.APPLICATION_JSON), expects.expects.toArray(new ResultMatcher[0])); } /** Post 要求 ( JSON ) を投げて結果を検証します。 */ protected ResultActions performJsonPost(String path, String content, final JsonExpects expects) { return performJsonPost(uriBuilder(path).build(), content, expects); } protected ResultActions performJsonPost(UriComponents uri, String content, final JsonExpects expects) { return perform( post(uri.toUriString()).contentType(MediaType.APPLICATION_JSON).content(content).accept(MediaType.APPLICATION_JSON), expects.expects.toArray(new ResultMatcher[0])); } protected ResultActions perform(final RequestBuilder req, final ResultMatcher... expects) { try { ResultActions result = mvc.perform(req); for (ResultMatcher matcher : expects) { result.andExpect(matcher); } return result; } catch (Exception e) { throw new InvocationException(e); } } /** JSON 検証をビルダー形式で可能にします */ public static class JsonExpects { public List<ResultMatcher> expects = new ArrayList<>(); public JsonExpects match(String key, Object expectedValue) { this.expects.add(jsonPath(key).value(expectedValue)); return this; } public <T> JsonExpects matcher(String key, Matcher<T> matcher) { this.expects.add(jsonPath(key).value(matcher)); return this; } public JsonExpects empty(String key) { this.expects.add(jsonPath(key).isEmpty()); return this; } public JsonExpects notEmpty(String key) { this.expects.add(jsonPath(key).isNotEmpty()); return this; } public JsonExpects array(String key) { this.expects.add(jsonPath(key).isArray()); return this; } public JsonExpects map(String key) { this.expects.add(jsonPath(key).isMap()); return this; } // 200 OK public static JsonExpects success() { JsonExpects v = new JsonExpects(); v.expects.add(status().isOk()); return v; } // 400 Bad Request public static JsonExpects failure() { JsonExpects v = new JsonExpects(); v.expects.add(status().isBadRequest()); return v; } } }