سؤال

أبحث حاليًا عن طرق لإنشاء اختبارات آلية لـ جاكس-RS (Java API for RESTful Web Services) خدمة ويب تعتمد على.

أحتاج بشكل أساسي إلى طريقة لإرسال مدخلات معينة إليه والتحقق من حصولي على الاستجابات المتوقعة.أفضّل القيام بذلك عبر JUnit، لكنني لست متأكدًا من كيفية تحقيق ذلك.

ما هو النهج الذي تستخدمه لاختبار خدمات الويب الخاصة بك؟

تحديث: كما أشار Entzik، فإن فصل خدمة الويب عن منطق الأعمال يسمح لي باختبار منطق الأعمال.ومع ذلك، أريد أيضًا اختبار رموز حالة HTTP الصحيحة وما إلى ذلك.

هل كانت مفيدة؟

المحلول

جيرسي يأتي مزودًا بواجهة برمجة تطبيقات عميل RESTful الرائعة التي تجعل اختبارات وحدة الكتابة أمرًا سهلاً للغاية.راجع اختبارات الوحدة في الأمثلة المرفقة مع Jersey.نحن نستخدم هذا الأسلوب لاختبار دعم REST في اباتشي الجمل, ، إذا كنت مهتما حالات الاختبار هنا

نصائح أخرى

يمكنك المحاولة اطمئن، لا تشغل بالك مما يجعلها جداً من السهل اختبار خدمات REST والتحقق من صحة الاستجابة في Java (باستخدام JUnit أو TestNG).

كما قال جيمس؛هناك مدمج إطار الاختبار لجيرسي.مثال بسيط لـ helloworld يمكن أن يكون كالتالي:

pom.xml للتكامل المخضرم.عند تشغيل mvn test.الأطر تبدأ حاوية أشيب.يمكنك استخدام رصيف المراكب الصغيرة أو القط عبر تغيير التبعيات.

...
<dependencies>
  <dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.16</version>
  </dependency>

  <dependency>
    <groupId>org.glassfish.jersey.test-framework</groupId>
    <artifactId>jersey-test-framework-core</artifactId>
    <version>2.16</version>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>2.16</version>
    <scope>test</scope>
  </dependency>
</dependencies>
...

exampleApp.java

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/")
public class ExampleApp extends Application {

}

HelloWorld.java

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/")
public final class HelloWorld {

    @GET
    @Path("/hello")
    @Produces(MediaType.TEXT_PLAIN)
    public String sayHelloWorld() {

        return "Hello World!";
    }
}

HelloWorldTest.java

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.core.Application;
import static org.junit.Assert.assertEquals;

public class HelloWorldTest extends JerseyTest {

    @Test
    public void testSayHello() {

        final String hello = target("hello").request().get(String.class);

        assertEquals("Hello World!", hello);
    }

    @Override
    protected Application configure() {

        return new ResourceConfig(HelloWorld.class);
    }
}

يمكنك التحقق هذا تطبيق عينة.

على الرغم من أن الوقت قد فات من تاريخ نشر السؤال، إلا أنني أعتقد أن هذا قد يكون مفيدًا للآخرين الذين لديهم سؤال مماثل.تأتي جيرسي مع إطار اختبار يسمى إطار اختبار جيرسي والذي يسمح لك باختبار خدمة RESTful Web Service، بما في ذلك رموز حالة الاستجابة.يمكنك استخدامه لإجراء اختباراتك على حاويات خفيفة الوزن مثل Grizzly و/أو HTTPServer و/أو EmbeddedGlassFish.كما يمكن استخدام إطار العمل لإجراء اختباراتك على حاوية ويب عادية مثل GlassFish أو Tomcat.

من المحتمل أنك كتبت بعض أكواد Java البرمجية التي تنفذ منطق عملك ثم قمت بإنشاء نقطة نهاية خدمات الويب لها.

الشيء المهم الذي يجب عليك فعله هو اختبار منطق عملك بشكل مستقل.نظرًا لأنه كود Java خالص، يمكنك القيام بذلك من خلال اختبارات JUnit العادية.

الآن، نظرًا لأن جزء خدمات الويب هو مجرد نقطة نهاية، فإن ما تريد التأكد منه هو أن السباكة التي تم إنشاؤها (بذرة، وما إلى ذلك) متزامنة مع كود جافا الخاص بك.يمكنك القيام بذلك عن طريق كتابة اختبارات JUnit التي تستدعي عملاء Java لخدمة الويب التي تم إنشاؤها.سيُعلمك هذا عندما تقوم بتغيير توقيعات جافا الخاصة بك دون تحديث عناصر خدمات الويب.

إذا تم إنشاء خدمات السباكة الخاصة بخدمات الويب الخاصة بك تلقائيًا بواسطة نظام البناء الخاص بك في كل بناء، فقد لا يكون من الضروري اختبار نقاط النهاية (بافتراض أنه تم إنشاؤها بشكل صحيح).يعتمد على مستوى جنون العظمة لديك.

أنا استخدم أباتشي عميل HTTP (http://hc.apache.org/) للاتصال بخدمات الراحة.تتيح لك مكتبة عميل HTTP إجراء عملية الحصول أو النشر أو أي عملية أخرى تحتاجها بسهولة.إذا كانت خدمتك تستخدم JAXB لربط XML، فيمكنك إنشاء JAXBContext لإجراء تسلسل وإلغاء تسلسل المدخلات والمخرجات من طلب HTTP.

نلقي نظرة على Alchemy مولد العميل الراحة.يمكن أن يؤدي ذلك إلى إنشاء تطبيق وكيل لفئة خدمة الويب JAX-RS الخاصة بك باستخدام عميل Jersey خلف الكواليس.على نحو فعال، ستستدعي أساليب خدمة الويب كأساليب جافا البسيطة من اختبارات الوحدة الخاصة بك.يتعامل مع مصادقة http أيضًا.

لا يتطلب الأمر إنشاء تعليمات برمجية إذا كنت بحاجة إلى إجراء الاختبارات ببساطة بحيث يكون ذلك مناسبًا.

إخلاء المسؤولية:أنا مؤلف هذه المكتبة.

الشيء المهم الذي يجب عليك فعله هو اختبار منطق عملك بشكل مستقل

بالتأكيد لن أفترض أن الشخص الذي كتب كود JAX-RS ويتطلع إلى اختبار الوحدة للواجهة هو بطريقة ما، لسبب غريب وغير قابل للتفسير، غافل عن فكرة أنه يمكنه اختبار الوحدة لأجزاء أخرى من البرنامج، بما في ذلك فئات منطق الأعمال.ليس من المفيد ذكر ما هو واضح، وقد تمت الإشارة مرارًا وتكرارًا إلى ضرورة اختبار الإجابات أيضًا.

يحتوي كل من Jersey وRESTEasy على تطبيقات عميل، وفي حالة RESTEasy، يمكنك استخدام نفس التعليقات التوضيحية (حتى استبعاد الواجهة المشروحة واستخدامها على جانب العميل والخادم في اختباراتك).

لا تقلق بشأن ما يمكن أن تفعله هذه الخدمة لك؛بقية ما يمكنك القيام به لهذه الخدمة.

أبقيها بسيطة.القي نظرة على https://github.com/valid4j/http-matchers والتي يمكن استيرادها من Maven Central.

    <dependency>
        <groupId>org.valid4j</groupId>
        <artifactId>http-matchers</artifactId>
        <version>1.0</version>
    </dependency>

مثال الاستخدام:

// Statically import the library entry point:
import static org.valid4j.matchers.http.HttpResponseMatchers.*;

// Invoke your web service using plain JAX-RS. E.g:
Client client = ClientBuilder.newClient();
Response response = client.target("http://example.org/hello").request("text/plain").get();

// Verify the response
assertThat(response, hasStatus(Status.OK));
assertThat(response, hasHeader("Content-Encoding", equalTo("gzip")));
assertThat(response, hasEntity(equalTo("content")));
// etc...

كما أفهم أن الغرض الرئيسي لمؤلف هذه المشكلة هو فصل طبقة JAX RS عن طبقة الأعمال.واختبار الوحدة فقط الأول.هناك مشكلتان أساسيتان يجب علينا حلهما:

  1. قم بإجراء اختبار بعض خادم الويب/التطبيق ، ووضع مكونات Jax RS فيه.وهم فقط.
  2. خدمات الأعمال وهمية داخل مكونات Jax RS/طبقة الراحة.

تم حل المشكلة الأولى باستخدام Arquillian.والثاني موصوف تماما في أركيليكان وهمي

فيما يلي مثال للكود، قد يختلف إذا كنت تستخدم خادم تطبيقات آخر، ولكن أتمنى أن تحصل على الفكرة والمزايا الأساسية.

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

import com.brandmaker.skinning.service.SomeBean;

/**
* Created by alexandr on 31.07.15.
*/
@Path("/entities")
public class RestBean
{
   @Inject
   SomeBean bean;

   @GET
   public String getEntiry()
   {
       return bean.methodToBeMoked();
   }
}

import java.util.Set;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

import com.google.common.collect.Sets;

/**
*/
@ApplicationPath("res")
public class JAXRSConfiguration extends Application
{
   @Override
   public Set<Class<?>> getClasses()
   {
       return Sets.newHashSet(RestBean.class);
   }
}


public class SomeBean
{
   public String methodToBeMoked()
   {
       return "Original";
   }
}

import javax.enterprise.inject.Specializes;

import com.brandmaker.skinning.service.SomeBean;

/**
*/
@Specializes
public class SomeBeanMock extends SomeBean
{
   @Override
   public String methodToBeMoked()
   {
       return "Mocked";
   }
}

@RunWith(Arquillian.class)
public class RestBeanTest
{
   @Deployment
   public static WebArchive createDeployment() {
       WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war")
               .addClasses(JAXRSConfiguration.class, RestBean.class, SomeBean.class, SomeBeanMock.class)
               .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
       System.out.println(war.toString(true));
       return war;
   }

   @Test
   public void should_create_greeting() {
       Client client = ClientBuilder.newClient();
       WebTarget target = client.target("http://127.0.0.1:8181/test/res/entities");
       //Building the request i.e a GET request to the RESTful Webservice defined
       //by the URI in the WebTarget instance.
       Invocation invocation = target.request().buildGet();
       //Invoking the request to the RESTful API and capturing the Response.
       Response response = invocation.invoke();
       //As we know that this RESTful Webserivce returns the XML data which can be unmarshalled
       //into the instance of Books by using JAXB.
       Assert.assertEquals("Mocked", response.readEntity(String.class));
   }
}

بضع ملاحظات:

  1. يتم استخدام تكوين JAX RS بدون web.xml هنا.
  2. يتم استخدام عميل JAX RS هنا (لا يوجد RESTEasy/Jersey، فهم يعرضون واجهة برمجة تطبيقات أكثر ملاءمة)
  3. عندما يبدأ الاختبار، يبدأ عداء Arquillian في العمل. هنا يمكنك العثور على كيفية تكوين اختبارات Arquillian باستخدام خادم التطبيقات المطلوب.
  4. اعتمادًا على خادم التطبيق المختار ، سيختلف عنوان URL في الاختبار قليلاً.يمكن استخدام منفذ آخر.8181 يستخدم بواسطة Glassfish مضمن في المثال الخاص بي.

نأمل، أنها سوف تساعد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top