1概要
私たちはしばらくの間、 私たちの簡単なReddit App のREST APIを構築してきました - それは、真剣になって テストを始める 時です。
これで、/reddit-app-replace-reddit-auth-with-form-based-login[最終的に切り替えられました]が、より単純な認証メカニズムにリンクされました。これも同様に簡単です。これらすべてのライブテストには、https://code.google.com/p/rest-assured/[強力な rest-assured ライブラリ]を使用します。
2初期設定
APIテストを実行するにはユーザーが必要です。 APIに対するテストの実行を簡単にするために、アプリケーションブートストラップで、事前にテストユーザーを作成します。
@Component
public class Setup {
@Autowired
private UserRepository userRepository;
@Autowired
private PreferenceRepository preferenceRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@PostConstruct
private void createTestUser() {
User userJohn = userRepository.findByUsername("john");
if (userJohn == null) {
userJohn = new User();
userJohn.setUsername("john");
userJohn.setPassword(passwordEncoder.encode("123"));
userJohn.setAccessToken("token");
userRepository.save(userJohn);
final Preference pref = new Preference();
pref.setTimezone(TimeZone.getDefault().getID());
pref.setEmail("[email protected]");
preferenceRepository.save(pref);
userJohn.setPreference(pref);
userRepository.save(userJohn);
}
}
}
Setup は単なるBeanであることに注意してください。実際のセットアップロジックには、@ @ PostConstruct__アノテーションを使用しています。
3ライブテストのサポート
実際にテストを書き始める前に、まず最初に基本的なサポート機能を設定しましょう。
認証、URLパス、そしていくつかのJSONのマーリングおよびアンマーシャル機能などが必要です。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
classes = { TestConfig.class },
loader = AnnotationConfigContextLoader.class)
public class AbstractLiveTest {
public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
@Autowired
private CommonPaths commonPaths;
protected String urlPrefix;
protected ObjectMapper objectMapper = new ObjectMapper().setDateFormat(dateFormat);
@Before
public void setup() {
urlPrefix = commonPaths.getServerRoot();
}
protected RequestSpecification givenAuth() {
FormAuthConfig formConfig
= new FormAuthConfig(urlPrefix + "/j__spring__security__check", "username", "password");
return RestAssured.given().auth().form("john", "123", formConfig);
}
protected RequestSpecification withRequestBody(RequestSpecification req, Object obj)
throws JsonProcessingException {
return req.contentType(MediaType.APPLICATION__JSON__VALUE)
.body(objectMapper.writeValueAsString(obj));
}
}
実際のテストを簡単にするために、単純なヘルパーメソッドとフィールドをいくつか定義しています。
-
givenAuth() :認証を実行します
-
withRequestBody() : Object のJSON表現を次のように送信します。
HTTPリクエストの本文
そして、これが私たちの単純なビーン CommonPaths です - システムのURLにきれいな抽象化を提供します:
@Component
@PropertySource({ "classpath:web-${envTarget:local}.properties" })
public class CommonPaths {
@Value("${http.protocol}")
private String protocol;
@Value("${http.port}")
private String port;
@Value("${http.host}")
private String host;
@Value("${http.address}")
private String address;
public String getServerRoot() {
if (port.equals("80")) {
return protocol + "://" + host + "/" + address;
}
return protocol + "://" + host + ":" + port + "/" + address;
}
}
そしてローカルバージョンのプロパティファイル: web-local.properties :
http.protocol=http
http.port=8080
http.host=localhost
http.address=reddit-scheduler
最後に、非常に単純なテストSpringの設定:
@Configuration
@ComponentScan({ "org.baeldung.web.live" })
public class TestConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
** 4/s _cheduledPosts _ APIをテストします.
**
最初にテストするAPIは /schedulePosts APIです。
public class ScheduledPostLiveTest extends AbstractLiveTest {
private static final String date = "2016-01-01 00:00";
private Post createPost() throws ParseException, IOException {
Post post = new Post();
post.setTitle("test");
post.setUrl("test.com");
post.setSubreddit("test");
post.setSubmissionDate(dateFormat.parse(date));
Response response = withRequestBody(givenAuth(), post)
.post(urlPrefix + "/api/scheduledPosts?date=" + date);
return objectMapper.reader().forType(Post.class).readValue(response.asString());
}
}
まず、新しい投稿のスケジュールをテストしましょう。
@Test
public void whenScheduleANewPost__thenCreated()
throws ParseException, IOException {
Post post = new Post();
post.setTitle("test");
post.setUrl("test.com");
post.setSubreddit("test");
post.setSubmissionDate(dateFormat.parse(date));
Response response = withRequestBody(givenAuth(), post)
.post(urlPrefix + "/api/scheduledPosts?date=" + date);
assertEquals(201, response.statusCode());
Post result = objectMapper.reader().forType(Post.class).readValue(response.asString());
assertEquals(result.getUrl(), post.getUrl());
}
次に、ユーザーの 予定されているすべての投稿を取得する ことをテストしましょう。
@Test
public void whenGettingUserScheduledPosts__thenCorrect()
throws ParseException, IOException {
createPost();
Response response = givenAuth().get(urlPrefix + "/api/scheduledPosts?page=0");
assertEquals(201, response.statusCode());
assertTrue(response.as(List.class).size() > 0);
}
次に、スケジュールされた投稿の編集** をテストしましょう。
@Test
public void whenUpdatingScheduledPost__thenUpdated()
throws ParseException, IOException {
Post post = createPost();
post.setTitle("new title");
Response response = withRequestBody(givenAuth(), post).
put(urlPrefix + "/api/scheduledPosts/" + post.getId() + "?date=" + date);
assertEquals(200, response.statusCode());
response = givenAuth().get(urlPrefix + "/api/scheduledPosts/" + post.getId());
assertTrue(response.asString().contains(post.getTitle()));
}
最後に、APIで 削除操作 をテストしましょう。
@Test
public void whenDeletingScheduledPost__thenDeleted()
throws ParseException, IOException {
Post post = createPost();
Response response = givenAuth().delete(urlPrefix + "/api/scheduledPosts/" + post.getId());
assertEquals(204, response.statusCode());
}
** 5/ sites API +をテストします.
**
次に、Sitesリソース(ユーザーが定義したサイト)を公開するAPIをテストしましょう。
public class MySitesLiveTest extends AbstractLiveTest {
private Site createSite() throws ParseException, IOException {
Site site = new Site("/feed/");
site.setName("baeldung");
Response response = withRequestBody(givenAuth(), site)
.post(urlPrefix + "/sites");
return objectMapper.reader().forType(Site.class).readValue(response.asString());
}
}
ユーザーのすべてのサイトを取得する** テストをしましょう
@Test
public void whenGettingUserSites__thenCorrect()
throws ParseException, IOException {
createSite();
Response response = givenAuth().get(urlPrefix + "/sites");
assertEquals(200, response.statusCode());
assertTrue(response.as(List.class).size() > 0);
}
また、サイトの記事を取得する:
@Test
public void whenGettingSiteArticles__thenCorrect()
throws ParseException, IOException {
Site site = createSite();
Response response = givenAuth().get(urlPrefix + "/sites/articles?id=" + site.getId());
assertEquals(200, response.statusCode());
assertTrue(response.as(List.class).size() > 0);
}
次に、 新しいサイトを追加する ことをテストしましょう。
@Test
public void whenAddingNewSite__thenCorrect()
throws ParseException, IOException {
Site site = createSite();
Response response = givenAuth().get(urlPrefix + "/sites");
assertTrue(response.asString().contains(site.getUrl()));
}
そしてそれを 削除 します。
@Test
public void whenDeletingSite__thenDeleted() throws ParseException, IOException {
Site site = createSite();
Response response = givenAuth().delete(urlPrefix + "/sites/" + site.getId());
assertEquals(204, response.statusCode());
}
6. /user/preferences API をテストします.
最後に、ユーザーの設定を公開するAPIに注目しましょう。
まず、 ユーザーの好みを取得する ことをテストしましょう。
@Test
public void whenGettingPrefernce__thenCorrect() {
Response response = givenAuth().get(urlPrefix + "/user/preference");
assertEquals(200, response.statusCode());
assertTrue(response.as(Preference.class).getEmail().contains("john"));
}
そしてそれらを 編集 します。
@Test
public void whenUpdattingPrefernce__thenCorrect()
throws JsonProcessingException {
Preference pref = givenAuth().get(urlPrefix + "/user/preference").as(Preference.class);
pref.setEmail("[email protected]");
Response response = withRequestBody(givenAuth(), pref).
put(urlPrefix + "/user/preference/" + pref.getId());
assertEquals(200, response.statusCode());
response = givenAuth().get(urlPrefix + "/user/preference");
assertEquals(response.as(Preference.class).getEmail(), pref.getEmail());
}
7. 結論
このクイック記事では、REST APIの基本的なテストをいくつかまとめました。
気を引くものは何もありません - より高度なシナリオが必要です - しかし** これは完璧ではなく、進歩と公の場での繰り返しについてです。