Advice on testing my classes that has many third party API calls.

View: New views
3 Messages — Rating Filter:   Alert me  

Advice on testing my classes that has many third party API calls.

by LadyCoconut :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello Everyone,

I have some experience in jMock. Currently using it with JUnit 3 (long story).

Anyway, I've had to develop a little application that depends heavily on third party libraries. The libraries are basically  used for pulling documents from a repository. Some of the classes have interfaces (not many) and there are many concrete classes.

Assume the following test code:

final IObjectService objectService = mock(IObjectService.class);
               
final DataPackage dataPackage = createDataPackage();
               
checking(new Expectations() {{
                oneOf (serviceContext).getIdentityCount(); will(returnValue(1));
                oneOf (serviceContext).setProfile(with(any(Profile.class)));
                oneOf (serviceFactory).getLocalService(with(IObjectService.class),
            with(serviceContext)); will(returnValue(objectService));
           
                oneOf (objectService).get(with(any(ObjectIdentitySet.class)),
            with(any(OperationOptions.class))); will(returnValue(dataPackage));
}});



Now here is the code that it is testing (bit ugly) but bear with me...

if(serviceContext.getIdentityCount() == 0) {
        serviceContext.addIdentity(repositoryIdentity);
}
               
ObjectId id = new ObjectId(objectId);
ObjectIdentity<ObjectId> objectIdentity = new ObjectIdentity<ObjectId>(id, repositoryIdentity.getRepositoryName());
               
ObjectIdentitySet objectIdSet = new ObjectIdentitySet();
objectIdSet.addIdentity(objectIdentity);
       
ContentTransferProfile transferProfile = new ContentTransferProfile();
transferProfile.setTransferMode(ContentTransferMode.MTOM);
transferProfile.setCachedContentTransferAllowed(true);
transferProfile.setAsyncContentTransferAllowed(true);
               
serviceContext.setProfile(transferProfile);
               
IObjectService objectService = serviceFactory.getLocalService(IObjectService.class, serviceContext);
               
OperationOptions operationsOptions = getOperationsOptionsProfile();
DataPackage dataPackage = objectService.get(objectIdSet, operationsOptions);
Content content = dataPackage.getDataObjects().get(0).getContents().get(0); //check



My questions are:

 1. in my test I am using the matchers with(any(OpertionOptions.class), with(any(Profile.class) and such....should I be mocking these concrete classes using the ClassImposteriser and setting them up and checking the exact expectations of these? It feels a bit wrong. All I want to test is that a call to the service is made and that I get back an expected type with some parameters in it?  

 2. Should I be spending my time skinning and wrapping the API for testing? As its rather a small project at the moment, I managed to create a stub service initially that returns some duff data.

Any thoughts would be welcome.

Regards



               

Re: Advice on testing my classes that has many third party API calls.

by Steve Freeman-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 27 Oct 2009, at 10:36, LadyCoconut wrote:

> My questions are:
>
> 1. in my test I am using the matchers with(any(OpertionOptions.class),
> with(any(Profile.class) and such....should I be mocking these concrete
> classes using the ClassImposteriser and setting them up and checking  
> the
> exact expectations of these? It feels a bit wrong. All I want to  
> test is
> that a call to the service is made and that I get back an expected  
> type with
> some parameters in it?

You want to check, for example, that the ObjectIdentitySet has been  
set up correctly? You could write a more precise matcher that checks  
the values within the ObjectIdSet that was passed in. Something like:

oneOf(objectService).get(with(objectIdentitySetWithId(1)), ...

If you just want to let the call go through, then the any() clauses  
are fine--that's your intention. You can simplify it further, if  
there's only one call to an object:

allowing(objectService); will(returnValue(dataPackage));

if that's all you care about. (Remember: Stub Queries, Expect Actions)

> 2. Should I be spending my time skinning and wrapping the API for  
> testing?
> As its rather a small project at the moment, I managed to create a  
> stub
> service initially that returns some duff data.

That depends :) At the least, I'd have some kind of interface in my  
domain code that protected me from the library, so there were no  
references.

S.

Steve Freeman

Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com

+44 (0) 797 179 4105
M3P Limited.  http://www.m3p.co.uk
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 03689627




---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Advice on testing my classes that has many third party API calls.

by LadyCoconut :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Steve Freeman-2 wrote:
On 27 Oct 2009, at 10:36, LadyCoconut wrote:
> My questions are:
>
> 1. in my test I am using the matchers with(any(OpertionOptions.class),
> with(any(Profile.class) and such....should I be mocking these concrete
> classes using the ClassImposteriser and setting them up and checking  
> the
> exact expectations of these? It feels a bit wrong. All I want to  
> test is
> that a call to the service is made and that I get back an expected  
> type with
> some parameters in it?

You want to check, for example, that the ObjectIdentitySet has been  
set up correctly? You could write a more precise matcher that checks  
the values within the ObjectIdSet that was passed in. Something like:

oneOf(objectService).get(with(objectIdentitySetWithId(1)), ...

If you just want to let the call go through, then the any() clauses  
are fine--that's your intention. You can simplify it further, if  
there's only one call to an object:

allowing(objectService); will(returnValue(dataPackage));

if that's all you care about. (Remember: Stub Queries, Expect Actions)

> 2. Should I be spending my time skinning and wrapping the API for  
> testing?
> As its rather a small project at the moment, I managed to create a  
> stub
> service initially that returns some duff data.

That depends :) At the least, I'd have some kind of interface in my  
domain code that protected me from the library, so there were no  
references.

S.

Steve Freeman

Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com

+44 (0) 797 179 4105
M3P Limited.  http://www.m3p.co.uk
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 03689627




---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Thanks for the advice and the reply.
Got your book in the post yesterday, looking forward to reading it.