Вопрос по unit-testing, rest, java, mockito – Как использовать mockito для тестирования службы REST?

24

Я очень новичок в модульном тестировании 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). Если все прошло хорошо, сервер должен ответить «Ваша схема была успешно создана!».

Может кто-нибудь, пожалуйста, помогите мне?

Где в приведенном выше коде вы отправляете строку JSON на сервер? Зачем вам вообще нужен Mockito для таких тестов? JB Nizet
Либо вы проводите интеграционные тесты и фактически отправляете JSON на свой сервер и анализируете полученный ответ, чтобы убедиться, что они уместны, либо вы проводите модульные тесты для тестирования методов ваших классов, используемых на стороне сервера. Мокито может быть полезным для последнего. Но, не видя ваш код, невозможно сказать вам, как его протестировать, кроме как указать на документацию Mockito. JB Nizet
Нет, это не так.rest это издевательство Это объект, который отвечает тому, что вы говорите ему отвечать. Это не ваш сервер отдыха. Вы тестируете Mockito вместо того, чтобы тестировать свой сервер. Вам не нужен Mockito для таких тестов. JB Nizet
Спасибо! Можете ли вы направить меня, как мне быть? Я хочу проверить свои методы CRUD. Я хочу модульные тесты, чтобы проверить каждый метод отдыха на моем сервере. Ion Morozan
Я не знаю, нужен ли мне Mockito для такого рода тестов, поскольку я сказал, что пытаюсь понять, как тестировать службу REST. Файл JSON отправляется, когда я вызываю этот метод:rest.initialize(DatabaseSchema) , DatabaseSchema это файл JSON Ion Morozan

Ваш Ответ

5   ответов
3

интеграционное тестирование и Mockito (или любые другие фальшивые фреймворки) вам не очень пригодятся.

Если вы хотите написать код для юнит-теста, который вы написали, Mockito, безусловно, является полезным инструментом.

Я предлагаю вам прочитать больше о насмешках / юнит-тестировании и в каких обстоятельствах его следует использовать.

@DavidWallace Согласен. Моя формулировка вводила в заблуждение, я имел в виду, что с тем, что описывает OP (развертывание его приложения и запуск REST-запросов), насмешка не будет иметь большого смысла.
Я не могу согласиться с этим ответом вообще. Я успешно использовал Mockito для множества интеграционных тестов. Часто существуют интеграционные тесты, в которых целые подсистемы не имеют отношения к делу и могут быть обоснованно подвергнуты фальсификации. Mockito (или некоторая другая среда для насмешек), как правило, полезна, когда вы хотите протестировать какую-то часть системы без взаимодействия с другими частями, которое скрывает то, что происходит в вашем тесте. Это может быть модульный тест, объемный тест или интеграционный тест.
0

что это не модульное тестирование, а интеграционное тестирование. В любом случае, вам лучше взглянуть на тесты джерси и встроенного сервера гризли. Подводя итог, этот код запускает сервер гризли (который также может запустить базу данных) по адресу localhost: 8888, затем настраивает клиента клиентского джерси и отправляет запрос POST, ответ на который должен быть проверен. Это интеграция, поскольку вы тестируете сервер и базу данных, однако вы можете использовать mockito для эмуляции базы данных, но это зависит от того, насколько связаны ваш сервер и база данных.

(тест с использованием джерси 1.11 и гризли 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

}
1

om.github.tomakehurst wiremock 2.4.1 org.igniterealtime.smack smack-core 4.0.6

Определите и используйте wiremock, как показано ниже

@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)));
2

portions кода; например, если вы потребляли свою службу REST, но не хотели выполнять полный тест стека, вы издеваетесь над службой, подключенной к службе REST, что позволяет вам точно и последовательно тестировать определенное поведение.

Чтобы протестировать внутренние части службы REST (например, конкретный метод службы), не обращаясь к базе данных, вы высмеиваете подсистему БД, позволяя тестировать только внутренние компоненты службы, не задействуя БД. Это тестирование принадлежит сервисному модулю REST, а не клиентской стороне.

Чтобы протестировать саму службу REST, вы используете реальную клиентскую библиотеку, создавая интеграционный тест с полным стеком. Здесь можно использовать Mockito, чтобы высмеивать части клиента, не связанные с потреблением услуг REST.

@IonMorozan Не уверен, что я понимаю вопрос - вы можете тестировать локально, вы можете тестировать развернутые, это зависит от того, что вы хотите протестировать. Запрос, вероятно, будетmade локально, независимо от конечной точки. @IonMorozan Not sure I understand the question--you can test locally, you can test deployed, it depends on which you want to test. The request would likely be made locally, regardless of the endpoint. –
Спасибо за ответ. На самом деле мне нужно протестировать разработанную мной службу REST, поэтому я хочу протестировать отдельные методы, но я не знаю, как это сделать. Например, как я сказал в своем вопросе, я хочу отправить JSON на сервер и проверить ответ. Я не знаю, где я должен сделать запрос, на локальном хосте или где я развернул API. Я использую GAE в качестве бэкэнда. Ion Morozan May 27 '12 at 16:19
23

проанализируйте входную строку как JSON и отправьте обратноBAD_REQUEST если он недействителен. Если это действительно так, создайте объект вdatastore с различными свойствами (вы их знаете) и отправить обратноOK.

И вам необходимо убедиться, что этот контракт выполняется методом.

Где Mockito помогает здесь? Ну, если вы тестируете этот метод без Mockito, вам нужен настоящийDataStoreService, и вам нужно убедиться, что объект был создан правильно в этом реальномDataStoreService, Это где ваш тест больше не является модульным тестом, и это также, где он слишком сложен для тестирования, слишком длинный и слишком сложный для выполнения, потому что ему нужна сложная среда.

Мокито может помочь, высмеивая зависимость от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
}
Метод тестирования должен быть в классе модульного теста, а не в классе, который вы тестируете. И EasyMock обычно используется сimport static org.mockito.Mockito.*, verify является статическим методом класса Mockito.
Спасибо! У меня есть вопрос: здесь должен был бытьverify(mockDataStoreService).put(argument.capture()); ? Даже если это произошло после того, как я перешел наmockDataStoreService Я получаю ошибкуThe method verify(DatastoreService) is undefined for the type MyRestService. Ion Morozan

Похожие вопросы