function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
MTBRiderMTBRider 

Collection store exception

I have a web service callout that is workign fine, but I cannot get the tests working for it.  The ws has two methods; init() and sync().  init() returns a String ans sync() returns List<String>

When I try to mock the response for the two WS methods in my test method, I get a an error:
Collection store exception putting myWS.syncResponse_element into MAP<String,myWS.initResponse_element>

So, it is trying to put one methods response into the response map of the other method.  

The WebServiceMock class looks like this:
@isTest
public class myWSMock implements WebServiceMock {

   public void doInvoke(Object stub, 
			Object request, 
			Map<String, Object> response,	
			String endpoint, 
			String soapAction,
			String requestName,	
			String responseNS, 
			String responseName,	
			String responseType) 				{
			
	myWS.initResponse_element r1 = new myWS.initResponse_element();
	myWS.syncResponse_element r2 = new myWS.syncResponse_element();
	r1.initReturn = 'response1';
	r2.syncReturn = new List<String>{'response2'};
	response.put('response_x', r1);
	response.put('response_x', r2);		
   }
}

I also tried structuring it with multiple mock response classes, one for each type of response, but I still get the Collection Store exception.

Thanks for your help.

pbattissonpbattisson
Can you try modifying the lines 18 and 19 to be

response.put('response_x', (Object)r1);
response.put('response_y', (Object)r2);

I have a feeling that because you are putting in an item r1 that is not a geenric object buut rather a specific class inheriting the object type that it is casting the map to be of type <String, myWS.initResponse_element>. Note as well how I have updated line 19 as it seemed you were opverwriting the item you had just placed on the map.
MTBRiderMTBRider
Thanks for the response.  Unfortunately I get the same Exception.

It seems as though there is a bug in the built in WebServiceMock class as no matter what I do the stack trace shows that it crashes when trying to initialize the response of one of the methods in the wsdl generate ws class.  This happens even when I create two seperate mock web service response classes and then only call one of them in my test class.  

It also seems unlikely that there could be a bug in this as I am sure there are many implementations of webservices within Salesforce that implement multiple methods that return different object types.

I keep going back to the fact that the generated ws class is labeling both of webservice methods returns as 'response_x', but as I said in my original post, the actual web service is working fine.  So obviously that is not an issue for the ws to function.  I would hate to have to go in a start making major changes to the generated WS class now just to get the test to run.

Any other ideas?  

Anyone else come across this?

Thanks

pbattissonpbattisson
Could you post the full exception up to help out. And the code from your test method calling this would help as well if possible.
MTBRiderMTBRider
Sure.  Here is the full Exception:

Exception Type = System.TypeException
Message = Collection store exception putting myWS.syncResponse_element into MAP<String,myWS.initResponse_element
Line Number = 18
Stack Trace = Class.myWSMock.doInvoke: line 18, column 1
Class.myWS.ListSyncWS.init: line 95, column 1	<-- Here is the class generated from the wsdl
Class.myWSCallout.doSync: line 56, column 1	<-- Here is the @future method making the callout

Here is the test:

@isTest
public class ContactAfterTest {
	
	@isTest
	static void ContactAfterTest() {
		List<Contact> tstCon = new List<Contact>;
		….
		//Insert a bunch of contacts for the test.  The @future call is called from an After Trigger
                ...
                myWSMock wsMock = new myWSMock();
                Test.setMock(WebServiceMock.class, wsMock);
		
                Test.startTest();
                    insert tstCon;
                Test.stopTest();
	}
}

As I said, I also tried breaking out the Mock responses into individual classes like so:

@isTest
global class myWSInitMock implements WebServiceMock {
	public String initResponse;
	
	global void doInvoke(Object stub, 
						Object request, 
						Map<String, Object> response,	
						String endpoint, 
						String soapAction,
						String requestName,	
						String responseNS, 
						String responseName,	
						String responseType) 				{
		
		myWS.initResponse_element resp = new myWS.initResponse_element();
		resp.initReturn = 'initTest';
		response.put('response_x', (Object)resp);
	}
}


@isTest
global class myWSSyncMock implements WebServiceMock {
	public List<String> syncResponse;
	
	global void doInvoke(Object stub, 
					Object request, 
					Map<String, Object> response,	
					String endpoint, 
					String soapAction,
					String requestName,	
					String responseNS, 
					String responseName,	
					String responseType) 		{
		myWS.syncResponse_element resp = new myWS.syncResponse_element();
		resp.syncReturn = new List<String>{'SyncTest'};
		response.put('response_x', (Object)resp);
	}
}

Modifying the test to only call one of the above mock response class gives me the same exception.

I simplified the actual web service method names, so hopefully I did not make any typos.

Thanks again for your help.




James LoghryJames Loghry
Strange issue you're running into..

Just looking briefly at your code,  you're using the same key when you put the diffferent classes into the map.

response.put('response_x', r1);
response.put('response_x', r2);


Note how they are both 'response_x'.

Did you try using different keys, as pbattinson suggested?  Could be that the map gets into some weird state where it expects the same type when you put a value into the map with the same key.

Also, what happens if you just take out the r1 class?  Do you still get an error then?

Lastly, have you tried casting both of the classes to the generic object type when you initialize them?  Something like below?  (Doubt it would work, but worth a shot)

public void doInvoke(Object stub,
            Object request,
            Map<String, Object> response,
            String endpoint,
            String soapAction,
            String requestName,
            String responseNS,
            String responseName,   
            String responseType){
    Object r1 = new myWS.initResponse_element();
    Object r2 = new myWS.syncResponse_element();
    ((myWS.initResponse_element)r1).initReturn = 'response1';
    ((myWS.initResponse_element)r2).syncReturn = new List<String>{'response2'};
    response.put('response_x', r1);
    response.put('response_y', r2);    
}


 

ZAPEXZAPEX
how was it solved ? I have the same issue?
ZAPEXZAPEX
Found the answer on stackexchange site. Here is the link.
http://salesforce.stackexchange.com/questions/40031/how-to-mock-metadataservice-cls-responses-in-testmethods-collection-store-exce