私は、GET、POST、UPDATE、DELETEという4つのメソッドでRestサービスを作成しました。 これらのメソッドは、データベースに接続してデータを取得および格納します。JAXRS + JerseyTest RESTサービスのテスト
今、それぞれの方法をテストしたいと思います。私はこれに対してJersey Test Frameworkを使用しました。そして、実際にデータベースを呼び出すコードを削除する限り、それは機能しています。データベースを呼び出すコードを残すと、データベースに接続できないという例外がスローされます。
編集:私はいくつかの研究を行い、依存性注入を使用しました。 dbコールは別のクラスに移動されますが、私はまだ何か間違っています。
DatabaseResults。このクラスでは、DBへの呼び出しが行われます。
public class DatabaseResults {
private final String getQuery = "SELECT * FROM movies";
private Connection connection = null;
private PreparedStatement pstmt = null;
private final ArrayList<Movie> jsonList = new ArrayList<>();
public JSONObject getAllMovies() throws SQLException {
try {
ComboPooledDataSource dataSource = DatabaseUtility.getDataSource();
connection = dataSource.getConnection();
pstmt = connection.prepareStatement(getQuery);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
jsonList.add(new Movie(rs.getString(1), rs.getString(2), rs.getString(4), rs.getString(3)));
}
} catch (SQLException ex) {
System.out.println(ex);
System.out.println("Could not retrieve a connection");
connection.rollback();
} finally {
connection.close();
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("movies", jsonList);
return jsonObject;
}
}
REST方式
@Path("movies")
public class MoviesResource {
....
private DatabaseResults dbResults = null;
public MoviesResource() {
this(new DatabaseResults());
}
MoviesResource(DatabaseResults dbr){
this.dbResults = dbr;
}
....
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAllMovies() throws JSONException, SQLException {
return Response.status(200).entity(dbResults.getAllMovies().toString()).build();
}
が含まれているMoviesResource Testクラス
@RunWith(MockitoJUnit44Runner.class)
public class MovieResourceTest extends JerseyTest {
JSONObject jsonObject = new JSONObject();
@Mock
DatabaseResults dbr;
@Before
public void setup() throws SQLException{
jsonObject.put("id", "hello");
when(dbr.getAllMovies()).thenReturn(jsonObject);
}
Client client = ClientBuilder.newClient();
WebTarget target = client
.target("http://localhost:9998/RestServiceMovies/resources");
@Override
protected Application configure() {
return new ResourceConfig(MoviesResource.class);
}
@Test
public void getAllMoviesTest() throws SQLException {
String responseGetAllMovies = target("/movies").request().get(String.class);
Assert.assertTrue("hello".equals(responseGetAllMovies));
}
この時点で、私はそれが呼び出しを行うgetAllMovies()
方法をテストするとき、私はまだテストを実行することができますが、 jsonObject
を返すのではなく、実際のデータベースに転送します。
モックオブジェクトとMovieResourceクラスのコンストラクタの間に接続がないと感じましたか?
RESTサービスが単一責任の原則に違反しているため、これはテストするのが難しいです。データベース・ロジックを別のクラスにカプセル化すると、そのクラスを簡単にモックしてRESTサービスを単独でテストできます。別の一般的なアプローチは、ユニットテストを実行して統合テストを実行することです。すなわち、メモリ内のデータベースを構成し、何も嘲笑しない。 – DavidS
だから私は別のクラスに自分のデータベースロジックをカプセル化しました。私はMockitoを使ってデータをモックしたいのですが、私は実際に私の 'getAllMovies'メソッドが模擬クラスを使うべきだとはどういうことがわかりません... – RSSD
これにはいくつかのアプローチがあります。あなたのRESTサービスがいくつかのプライベートフィールドにアクセスしているとします。 'moviesDatabase'です。このオブジェクトまたはそのメソッドをモックしたいので、使用する 'moviesDatabase'があるRESTサービスに何らかの方法を伝える必要があります。あなたのオプションは:(1)コンストラクタインジェクション(2)フィールドをpackage-privateにして、それを直接設定する(3)DaggerやWeldのようなファンシー依存性注入フレームワークを使用する。 – DavidS