26

私は Java ユニット テストを始めたばかりで、Mockito フレームワークはテスト目的に非常に適していると聞きました。

REST サーバー (CRUD メソッド) を開発したので、それをテストしたいのですが、方法がわかりません。

さらに、このテスト手順をどのように開始すればよいかわかりません。サーバーは localhost で動作し、その URL (例: localhost:8888) で呼び出しを行う必要がありますか?

これが私がこれまでに試したことですが、これは正しい方法ではないと確信しています。

    @Test
    public void testInitialize() {
        RESTfulGeneric rest = mock(RESTfulGeneric.class);

        ResponseBuilder builder = Response.status(Response.Status.OK);

        builder = Response.status(Response.Status.OK).entity(
                "Your schema was succesfully created!");

        when(rest.initialize(DatabaseSchema)).thenReturn(builder.build());

        String result = rest.initialize(DatabaseSchema).getEntity().toString();

        System.out.println("Here: " + result);

        assertEquals("Your schema was succesfully created!", result);

    }

initializeメソッドのコードは次のとおりです。

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/initialize")
    public Response initialize(String DatabaseSchema) {

        /** Set the LogLevel to Info, severe, warning and info will be written */
        LOGGER.setLevel(Level.INFO);

        ResponseBuilder builder = Response.status(Response.Status.OK);

        LOGGER.info("POST/initialize - Initialize the " + user.getUserEmail()
                + " namespace with a database schema.");

        /** Get a handle on the datastore itself */
        DatastoreService datastore = DatastoreServiceFactory
                .getDatastoreService();


        datastore.put(dbSchema);

        builder = Response.status(Response.Status.OK).entity(
                "Your schema was succesfully created!");
        /** Send response */
        return builder.build();
    }

このテスト ケースでは、Json 文字列をサーバー (POST) に送信します。すべてがうまくいった場合、サーバーは「スキーマが正常に作成されました!」と応答するはずです。

誰か助けてくれませんか?

4

5 に答える 5

24

わかった。BAD_REQUESTしたがって、メソッドの契約は次のとおりです。入力文字列を JSON として解析し、無効な場合は送り返します。datastore有効な場合は、さまざまなプロパティ (ご存知のとおり) を使用して にエンティティを作成し、を返送しOKます。

そして、このコントラクトがメソッドによって履行されていることを確認する必要があります。

ここで Mockito はどこで役立ちますか? Mockito を使用せずにこのメソッドをテストする場合は、 real が必要DataStoreServiceであり、エンティティがこの real で正しく作成されていることを確認する必要がありますDataStoreService。これは、テストがもはや単体テストではない場所であり、複雑な環境が必要なため、テストが複雑すぎ、長すぎ、実行が難しすぎる場所でもあります。

Mockito は、 への依存関係をモックすることで役立ちDataStoreServiceます。 のモックを作成し、テストでメソッドDataStoreServiceを呼び出すときに、このモックが適切なエンティティ引数で実際に呼び出されることを確認できます。initialize()

DataStoreServiceそのためには、テスト対象のオブジェクトにを注入できる必要があります。次の方法でオブジェクトをリファクタリングするのと同じくらい簡単です。

public class MyRestService {
    private DataStoreService dataStoreService;

    // constructor used on the server
    public MyRestService() {
        this.dataStoreService = DatastoreServiceFactory.getDatastoreService();
    }

    // constructor used by the unit tests
    public MyRestService(DataStoreService dataStoreService) {
        this.dataStoreService = dataStoreService;
    }

    public Response initialize(String DatabaseSchema) {
         ...
         // use this.dataStoreService instead of datastore
    }
}

これで、テスト メソッドで次のことができます。

@Test
public void testInitializeWithGoodInput() {
    DataStoreService mockDataStoreService = mock(DataStoreService.class);
    MyRestService service = new MyRestService(mockDataStoreService);
    String goodInput = "...";
    Response response = service.initialize(goodInput);
    assertEquals(Response.Status.OK, response.getStatus());

    ArgumentCaptor<Entity> argument = ArgumentCaptor.forClass(Entity.class);
    verify(mock).put(argument.capture());
    assertEquals("the correct kind", argument.getValue().getKind());
    // ... other assertions
}
于 2012-05-27T16:50:01.230 に答える
3

あなたが話していることは、統合テストのように聞こえます.Mockito(または他のモッキングフレームワーク)は、あまり役に立ちません。

作成したコードを単体テストする場合、Mockito は確かに便利なツールです。

モック/単体テストと、それを使用する必要がある状況について詳しく読むことをお勧めします。

于 2012-05-27T15:58:08.293 に答える
2

最良の方法は、wiremock を使用することです 次の依存関係を追加します com.github.tomakehurst wiremock 2.4.1 org.igniterealtime.smack smack-core 4.0.6

以下に示すように、ワイヤーモックを定義して使用します

@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);

String response ="Hello world";
StubMapping responseValid = stubFor(get(urlEqualTo(url)).withHeader("Content-Type", equalTo("application/json"))
        .willReturn(aResponse().withStatus(200)
                .withHeader("Content-Type", "application/json").withBody(response)));
于 2016-12-01T10:45:55.007 に答える
2

Mockito は (一般に)コードの一部をテストするためのものです。たとえば、REST サービスを使用しているが、フルスタック テストを実行したくない場合は、REST サービスに接続されているサービスをモックして、特定の動作を正確かつ一貫してテストできるようにします。

データベースにアクセスせずに REST サービスの内部部分 (特定のサービス メソッドなど) をテストするには、DB サブシステムをモックして、DB を使用せずにサービス内部のみをテストできるようにします。このテストは、クライアント側ではなく、REST サービス モジュールに属します。

REST サービス自体をテストするには、実際のクライアント ライブラリを使用して、フルスタックの統合テストを作成します。ここで Mockito を使用して、REST サービスの消費に関係のないクライアントの部分をモックできます。

于 2012-05-27T16:03:44.930 に答える
0

これは単体テストではなく統合テストであることに同意します。とにかく、ジャージーと組み込みのグリズリーサーバーテストを見てみたいと思います。要約すると、このコードは localhost:8888 でグリズリー サーバー (データベースも起動できる) を起動し、クライアントのジャージのクライアントをセットアップして、応答をテストする必要がある POST 要求を送信します。サーバーとデータベースの両方をテストしているため、これは統合です。ただし、mockito を使用してデータベースをエミュレートすることはできますが、サーバーとデータベースがどの程度結びついているかによって異なります。

(jersey 1.11 と grizzly 2.2 を使用してテスト)

    @BeforeClass
    public static void setUpClass() throws Exception {
        // starts grizzly
        Starter.start_grizzly(true);
        Thread.sleep(4000);
    }

    @Before
    public void setUp() throws Exception {
        client = new Client();
        webResource = client.resource("http://localhost:8888");
    }   

    @Test
    public void testPostSchemaDatabase() throws Exception {
        {
            String DatabaseSchema = "{ database_schema : {...}}";
            logger.info("REST client configured to send: "  + DatabaseSchema);
            ClientResponse response =  
                    webResource
                             .path("/initialize")
                             .type("application/json")
                             .post(ClientResponse.class, DatabaseSchema);
            //wait for the server to process
            Thread.sleep(2000);
            assertEquals(response.getStatus(), 204);    
            //test the response
        }       
    }

    @After
    public void after() throws JSONException
    {
            //probably you want to delete the schema at database and stop the server

}
于 2012-05-28T06:42:07.247 に答える