You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by cganesan <ch...@hp.com> on 2012/02/01 20:41:44 UTC
Unit testing JAX-RS services
Hi
Is there a way to invoke the URLs for a JAX-RS end point services as part of
JUnit test - triggered from MAven build? Does Apache CXF support something
like an embedded container towards this?
Thanks
Chandru
--
View this message in context: http://cxf.547215.n5.nabble.com/Unit-testing-JAX-RS-services-tp5448539p5448539.html
Sent from the cxf-user mailing list archive at Nabble.com.
Re: Unit testing JAX-RS services
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 16/02/12 02:54, Jeff Wang wrote:
> Sorry, didn't see this message until just now...
>
> On Fri, Feb 3, 2012 at 9:42 AM, Sergey Beryozkin<sb...@gmail.com> wrote:
>> On 03/02/12 03:02, Jeff Wang wrote:
>>>
>>> I'm having two difficulties with testing. One practical, one theoretical.
>>>
>>> practical:
>>> If I have any @Context annotations, I can't actually call the service
>>> via a client proxy. I need to code the call separately (and
>>> manually.)
>>>
>> I updated the proxies to simply ignore explicit Context parameters, they are
>> only populated on the server side...You'd need to pass 'null' if you have
>> explicit Context params, in meantime try injecting Contexts into fields...
>
> I've had @Context UriInfo turn up null before when field-injected
> (same code works method injected), but that was a long time ago. I'll
> try this later today.
>
>>> theoretical:
>>> Using the same JSON compile unit on the service and the test seems to
>>> defeat the purpose. If I have a webpage hitting my JAX-RS server, and
>>> I change the name of a field, I'd like to have my test point that out,
>>> so that when I fix my test, I can let my web team know. But if I use
>>> the same compile unit, whatever I change, even accidentally, will
>>> marshall and unmarshall correctly, the actual user of the API may then
>>> run into issues.
>>>
>> I'm not sure I understand completely, but just in case, it's possible to
>> adapt the in/out JSON sequences to the expected ones with the help of
>> TransformFeature, but only if the default JSONProvider is used
>
> What I mean is, let's say I have a Book object. And I accidentally
> add "asdf" to the name element of a field. I would have broken every
> single one of the actual clients that called Bookstore.findBook(id),
> but if I use either a direct client call or a proxy, the tests would
> pass. Essentially, if you're using the same class file on the client
> side and the server side, all you're really doing is testing that
> marshall and unmarshall works (the framework.) Not that your JAXB
> mapping or CXF annotation is correct (the actual code that you need to
> write.)
>
I think I see what you mean this time...Note though, TransformFeature
can also be used to 'drop' the new elements the clients which are only
aware of the previous 'version' of the given payload do not expect -
sorry, may be it is off topic
Sergey
> While testing the framework is useful and have pointed out some
> mapping mistakes to me, I would bet that the majority of programmer
> errors lie in the actual code, and not in the framework.
>
> Jeff
>
>>
>> Sergey
>>
>>
>>> Jeff
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com
Re: Unit testing JAX-RS services
Posted by Jeff Wang <je...@plutom.com>.
Sorry, didn't see this message until just now...
On Fri, Feb 3, 2012 at 9:42 AM, Sergey Beryozkin <sb...@gmail.com> wrote:
> On 03/02/12 03:02, Jeff Wang wrote:
>>
>> I'm having two difficulties with testing. One practical, one theoretical.
>>
>> practical:
>> If I have any @Context annotations, I can't actually call the service
>> via a client proxy. I need to code the call separately (and
>> manually.)
>>
> I updated the proxies to simply ignore explicit Context parameters, they are
> only populated on the server side...You'd need to pass 'null' if you have
> explicit Context params, in meantime try injecting Contexts into fields...
I've had @Context UriInfo turn up null before when field-injected
(same code works method injected), but that was a long time ago. I'll
try this later today.
>> theoretical:
>> Using the same JSON compile unit on the service and the test seems to
>> defeat the purpose. If I have a webpage hitting my JAX-RS server, and
>> I change the name of a field, I'd like to have my test point that out,
>> so that when I fix my test, I can let my web team know. But if I use
>> the same compile unit, whatever I change, even accidentally, will
>> marshall and unmarshall correctly, the actual user of the API may then
>> run into issues.
>>
> I'm not sure I understand completely, but just in case, it's possible to
> adapt the in/out JSON sequences to the expected ones with the help of
> TransformFeature, but only if the default JSONProvider is used
What I mean is, let's say I have a Book object. And I accidentally
add "asdf" to the name element of a field. I would have broken every
single one of the actual clients that called Bookstore.findBook(id),
but if I use either a direct client call or a proxy, the tests would
pass. Essentially, if you're using the same class file on the client
side and the server side, all you're really doing is testing that
marshall and unmarshall works (the framework.) Not that your JAXB
mapping or CXF annotation is correct (the actual code that you need to
write.)
While testing the framework is useful and have pointed out some
mapping mistakes to me, I would bet that the majority of programmer
errors lie in the actual code, and not in the framework.
Jeff
>
> Sergey
>
>
>> Jeff
Re: Unit testing JAX-RS services
Posted by Sergey Beryozkin <sb...@gmail.com>.
On 03/02/12 03:02, Jeff Wang wrote:
> I'm having two difficulties with testing. One practical, one theoretical.
>
> practical:
> If I have any @Context annotations, I can't actually call the service
> via a client proxy. I need to code the call separately (and
> manually.)
>
I updated the proxies to simply ignore explicit Context parameters, they
are only populated on the server side...You'd need to pass 'null' if you
have explicit Context params, in meantime try injecting Contexts into
fields...
> theoretical:
> Using the same JSON compile unit on the service and the test seems to
> defeat the purpose. If I have a webpage hitting my JAX-RS server, and
> I change the name of a field, I'd like to have my test point that out,
> so that when I fix my test, I can let my web team know. But if I use
> the same compile unit, whatever I change, even accidentally, will
> marshall and unmarshall correctly, the actual user of the API may then
> run into issues.
>
I'm not sure I understand completely, but just in case, it's possible to
adapt the in/out JSON sequences to the expected ones with the help of
TransformFeature, but only if the default JSONProvider is used
Sergey
> Jeff
>
> On Thu, Feb 2, 2012 at 1:49 PM, Glen Mazza<gm...@talend.com> wrote:
>> I recently converted the Jersey "helloworld" sample to using CXF, its JUnit
>> test case structure might be something you can leverage:
>>
>> https://github.com/gmazza/jersey-samples-on-cxf/tree/master/helloworld/src/test/java/com/sun/jersey/samples/helloworld
>>
>> HTH,
>> Glen
>>
>>
>> On 02/01/2012 02:41 PM, cganesan wrote:
>>>
>>> Hi
>>>
>>> Is there a way to invoke the URLs for a JAX-RS end point services as part
>>> of
>>> JUnit test - triggered from MAven build? Does Apache CXF support something
>>> like an embedded container towards this?
>>>
>>> Thanks
>>> Chandru
>>>
>>> --
>>> View this message in context:
>>> http://cxf.547215.n5.nabble.com/Unit-testing-JAX-RS-services-tp5448539p5448539.html
>>> Sent from the cxf-user mailing list archive at Nabble.com.
>>
>>
>>
>> --
>> Glen Mazza
>> Talend Community Coders - coders.talend.com
>> blog: www.jroller.com/gmazza
>>
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com
Re: Unit testing JAX-RS services
Posted by Jeff Wang <je...@plutom.com>.
I'm having two difficulties with testing. One practical, one theoretical.
practical:
If I have any @Context annotations, I can't actually call the service
via a client proxy. I need to code the call separately (and
manually.)
theoretical:
Using the same JSON compile unit on the service and the test seems to
defeat the purpose. If I have a webpage hitting my JAX-RS server, and
I change the name of a field, I'd like to have my test point that out,
so that when I fix my test, I can let my web team know. But if I use
the same compile unit, whatever I change, even accidentally, will
marshall and unmarshall correctly, the actual user of the API may then
run into issues.
Jeff
On Thu, Feb 2, 2012 at 1:49 PM, Glen Mazza <gm...@talend.com> wrote:
> I recently converted the Jersey "helloworld" sample to using CXF, its JUnit
> test case structure might be something you can leverage:
>
> https://github.com/gmazza/jersey-samples-on-cxf/tree/master/helloworld/src/test/java/com/sun/jersey/samples/helloworld
>
> HTH,
> Glen
>
>
> On 02/01/2012 02:41 PM, cganesan wrote:
>>
>> Hi
>>
>> Is there a way to invoke the URLs for a JAX-RS end point services as part
>> of
>> JUnit test - triggered from MAven build? Does Apache CXF support something
>> like an embedded container towards this?
>>
>> Thanks
>> Chandru
>>
>> --
>> View this message in context:
>> http://cxf.547215.n5.nabble.com/Unit-testing-JAX-RS-services-tp5448539p5448539.html
>> Sent from the cxf-user mailing list archive at Nabble.com.
>
>
>
> --
> Glen Mazza
> Talend Community Coders - coders.talend.com
> blog: www.jroller.com/gmazza
>
Re: Unit testing JAX-RS services
Posted by Glen Mazza <gm...@talend.com>.
I recently converted the Jersey "helloworld" sample to using CXF, its
JUnit test case structure might be something you can leverage:
https://github.com/gmazza/jersey-samples-on-cxf/tree/master/helloworld/src/test/java/com/sun/jersey/samples/helloworld
HTH,
Glen
On 02/01/2012 02:41 PM, cganesan wrote:
> Hi
>
> Is there a way to invoke the URLs for a JAX-RS end point services as part of
> JUnit test - triggered from MAven build? Does Apache CXF support something
> like an embedded container towards this?
>
> Thanks
> Chandru
>
> --
> View this message in context: http://cxf.547215.n5.nabble.com/Unit-testing-JAX-RS-services-tp5448539p5448539.html
> Sent from the cxf-user mailing list archive at Nabble.com.
--
Glen Mazza
Talend Community Coders - coders.talend.com
blog: www.jroller.com/gmazza
Re: Unit testing JAX-RS services
Posted by Kiren Pillay <ki...@gmail.com>.
I would suggest having a look at the Unit tests that come with CXF, they
seem to have a simpler way of doing this.
Regards
Kiren
On Wed, Feb 1, 2012 at 10:21 PM, KARR, DAVID <dk...@att.com> wrote:
> > -----Original Message-----
> > From: cganesan [mailto:chandru.ganesan@hp.com]
> > Sent: Wednesday, February 01, 2012 11:42 AM
> > To: users@cxf.apache.org
> > Subject: Unit testing JAX-RS services
> >
> > Hi
> >
> > Is there a way to invoke the URLs for a JAX-RS end point services as
> > part of
> > JUnit test - triggered from MAven build? Does Apache CXF support
> > something
> > like an embedded container towards this?
>
> Yes. The core of this support is the
> "org.apache.cxf.jaxrs.JAXRSServerFactoryBean" class. It internally manages
> an embedded Jetty server that your service is automatically deployed to.
> You can then use the "WebClient" class to connect to the server and get a
> response.
>
> You'll probably find more history on this topic by searching the mailing
> list (some of it from me).
>
> What's somewhat annoying is that you have to manually (as far as I can
> tell) set the parameters for your JAX-RS server (which that class is
> defining), instead of just using the settings from the Spring context.
> I've defined a "ServerFactory" class with a "create()" method that sets
> the properties that I need. I'll show that method here, but note that I'm
> only setting properties that my app uses. You may have other needs.
>
> public static void create(Object serviceBean, JSONProvider
> jsonProvider, String uri) {
> JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
>
> BindingFactoryManager manager =
> sf.getBus().getExtension(BindingFactoryManager.class);
> JAXRSBindingFactory factory = new JAXRSBindingFactory();
> factory.setBus(sf.getBus());
>
> manager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID,
> factory);
>
> if (jsonProvider == null) {
> Map<String, String> namespaceMap = new HashMap<String,
> String>();
> XmlSchema xmlSchemaAnnotation =
> ServiceCallResults.class.getPackage().getAnnotation(XmlSchema.class);
> namespaceMap.put(xmlSchemaAnnotation.namespace(), "cns");
> jsonProvider = new JSONProvider();
> jsonProvider.setNamespaceMap(namespaceMap);
> jsonProvider.setIgnoreNamespaces(false);
> }
>
> sf.setProvider(jsonProvider);
>
> setJSONProvider(jsonProvider);
>
> Map<Object, Object> extensionsMap = new HashMap<Object, Object>();
> extensionsMap.put("json", "application/json");
> extensionsMap.put("xml", "application/xml");
>
> sf.setExtensionMappings(extensionsMap);
>
> sf.setServiceBean(serviceBean);
> sf.getInInterceptors().add(new LoggingInInterceptor());
> sf.getOutInterceptors().add(new LoggingOutInterceptor());
>
> sf.setAddress(uri);
>
> sf.create();
> }
>
> Using this, I can write an integration test (I don't call this a unit
> test) with a @BeforeClass method that initializes the server with my
> service beans, and then my test methods just use WebClient.
>
>
Re: Unit testing JAX-RS services
Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
The local transport for proxy-based JAX-RS clients will also be
supported as soon as the client runtime becomes 'free' from
HttpURLConnection references.
Cheers, Sergey
On 01/02/12 20:21, KARR, DAVID wrote:
>> -----Original Message-----
>> From: cganesan [mailto:chandru.ganesan@hp.com]
>> Sent: Wednesday, February 01, 2012 11:42 AM
>> To: users@cxf.apache.org
>> Subject: Unit testing JAX-RS services
>>
>> Hi
>>
>> Is there a way to invoke the URLs for a JAX-RS end point services as
>> part of
>> JUnit test - triggered from MAven build? Does Apache CXF support
>> something
>> like an embedded container towards this?
>
> Yes. The core of this support is the "org.apache.cxf.jaxrs.JAXRSServerFactoryBean" class. It internally manages an embedded Jetty server that your service is automatically deployed to. You can then use the "WebClient" class to connect to the server and get a response.
>
> You'll probably find more history on this topic by searching the mailing list (some of it from me).
>
> What's somewhat annoying is that you have to manually (as far as I can tell) set the parameters for your JAX-RS server (which that class is defining), instead of just using the settings from the Spring context. I've defined a "ServerFactory" class with a "create()" method that sets the properties that I need. I'll show that method here, but note that I'm only setting properties that my app uses. You may have other needs.
>
> public static void create(Object serviceBean, JSONProvider jsonProvider, String uri) {
> JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
>
> BindingFactoryManager manager = sf.getBus().getExtension(BindingFactoryManager.class);
> JAXRSBindingFactory factory = new JAXRSBindingFactory();
> factory.setBus(sf.getBus());
> manager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID, factory);
>
> if (jsonProvider == null) {
> Map<String, String> namespaceMap = new HashMap<String, String>();
> XmlSchema xmlSchemaAnnotation = ServiceCallResults.class.getPackage().getAnnotation(XmlSchema.class);
> namespaceMap.put(xmlSchemaAnnotation.namespace(), "cns");
> jsonProvider = new JSONProvider();
> jsonProvider.setNamespaceMap(namespaceMap);
> jsonProvider.setIgnoreNamespaces(false);
> }
>
> sf.setProvider(jsonProvider);
>
> setJSONProvider(jsonProvider);
>
> Map<Object, Object> extensionsMap = new HashMap<Object, Object>();
> extensionsMap.put("json", "application/json");
> extensionsMap.put("xml", "application/xml");
>
> sf.setExtensionMappings(extensionsMap);
>
> sf.setServiceBean(serviceBean);
> sf.getInInterceptors().add(new LoggingInInterceptor());
> sf.getOutInterceptors().add(new LoggingOutInterceptor());
>
> sf.setAddress(uri);
>
> sf.create();
> }
>
> Using this, I can write an integration test (I don't call this a unit test) with a @BeforeClass method that initializes the server with my service beans, and then my test methods just use WebClient.
>
RE: Unit testing JAX-RS services
Posted by "KARR, DAVID" <dk...@att.com>.
> -----Original Message-----
> From: cganesan [mailto:chandru.ganesan@hp.com]
> Sent: Wednesday, February 01, 2012 11:42 AM
> To: users@cxf.apache.org
> Subject: Unit testing JAX-RS services
>
> Hi
>
> Is there a way to invoke the URLs for a JAX-RS end point services as
> part of
> JUnit test - triggered from MAven build? Does Apache CXF support
> something
> like an embedded container towards this?
Yes. The core of this support is the "org.apache.cxf.jaxrs.JAXRSServerFactoryBean" class. It internally manages an embedded Jetty server that your service is automatically deployed to. You can then use the "WebClient" class to connect to the server and get a response.
You'll probably find more history on this topic by searching the mailing list (some of it from me).
What's somewhat annoying is that you have to manually (as far as I can tell) set the parameters for your JAX-RS server (which that class is defining), instead of just using the settings from the Spring context. I've defined a "ServerFactory" class with a "create()" method that sets the properties that I need. I'll show that method here, but note that I'm only setting properties that my app uses. You may have other needs.
public static void create(Object serviceBean, JSONProvider jsonProvider, String uri) {
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
BindingFactoryManager manager = sf.getBus().getExtension(BindingFactoryManager.class);
JAXRSBindingFactory factory = new JAXRSBindingFactory();
factory.setBus(sf.getBus());
manager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID, factory);
if (jsonProvider == null) {
Map<String, String> namespaceMap = new HashMap<String, String>();
XmlSchema xmlSchemaAnnotation = ServiceCallResults.class.getPackage().getAnnotation(XmlSchema.class);
namespaceMap.put(xmlSchemaAnnotation.namespace(), "cns");
jsonProvider = new JSONProvider();
jsonProvider.setNamespaceMap(namespaceMap);
jsonProvider.setIgnoreNamespaces(false);
}
sf.setProvider(jsonProvider);
setJSONProvider(jsonProvider);
Map<Object, Object> extensionsMap = new HashMap<Object, Object>();
extensionsMap.put("json", "application/json");
extensionsMap.put("xml", "application/xml");
sf.setExtensionMappings(extensionsMap);
sf.setServiceBean(serviceBean);
sf.getInInterceptors().add(new LoggingInInterceptor());
sf.getOutInterceptors().add(new LoggingOutInterceptor());
sf.setAddress(uri);
sf.create();
}
Using this, I can write an integration test (I don't call this a unit test) with a @BeforeClass method that initializes the server with my service beans, and then my test methods just use WebClient.