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
MarcFogMarcFog 

No Apex class named 'ParkServiceMock' was found

Greetings - has anyone received the error "No Apex class named 'ParkServiceMock' was found."? I have the ParkServiceMock class defined, and called out in the ParkLocatorTest class using Test.setMock(WebServiceMock.class, new ParkServiceMock());

I also verified that the tests run with 100% code coverage, and the ParkLocator class returns the names of parks. 

Any idea what I'm doing wrong?  Thanks in advance.  
PavanKPavanK
Can you please post code or provide more detail?
MarcFogMarcFog
Hi PavanK - thank you for the quick reply.  I'm using the ParkService generated from the WSDL.  

ParkLocatorTest
@isTest
private class ParkLocatorTest {
    @isTest static void testCallout() {              
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        // Call the method that invokes a callout
        String[] parks = ParkLocator.Country('Japan');
        // Verify that a fake result is returned
        system.assert(parks.size() > 0);
    }
}

ParkLocator
public class ParkLocator {
    public static List<String> Country(String name) {
        List<String> countries = new List<String>();
 		ParkService.ParksImplPort park = new ParkService.ParksImplPort();
        countries = park.byCountry(name);
        return countries;
    }
}

and ParkServiceMock
@isTest
global class ParkServiceMock implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
        	// start - specify the response you want to send
        	ParkService.byCountryResponse response_x = new ParkService.byCountryResponse();
               response_x.return_x = new List<String>{'Shiretoko National Park', 'Oze National Park', 'Hakusan National Park'};
            response.put('response_x', response_x); 
   }
}

I greatly appreciate any insight into what's going wrong.  

Marc
David Bailey 16David Bailey 16
Greetings Mark,

Um, this is not an "Answer", as I am getting the same error from the Apex SOAP Callouts challenge.  To wit:

Apex SOAP Callouts Challenge ParkServiceMock Class Not Found Error

In my case, I incorrectly named the mock class as ParkLocatorMock.apxc when I created it initially.  So, I legitimately got the error at first.  I quickly realized that I 'fumble-brained' the naming, so I then created the class named properly.  I re-ran my tests and got the same error again.  So I deleted the incorrectly named class, performed a Clear Text Data, and performed a Run All, but the error persisted.

Here is all of the pertinent code ...

My ParkLocator.apxc file:
 
public class ParkLocator {
    public static String[] country(String x) {
        ParkService.ParksImplPort parks = 
            new ParkService.ParksImplPort();
        return parks.byCountry(x);
    }
}



My ParkLocatorTest.apxc file:
 
@isTest
private class ParkLocatorTest {
    @isTest static void testCallout() {              
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        // Call the method that invokes a callout
        String inputCountry = 'United States';
        String[] result = ParkLocator.country(inputCountry);
        // Verify that a fake result is returned
        String[] mockResult = new String[]{'a','b','c'};
        System.assertEquals(mockResult, result); 
        System.debug('ParkLocatorTest result: ' + result);
        System.debug('ParkLocatorTest mockResult: ' + mockResult);
    }
}


My ParkServiceMock.apxc file:
 
@isTest
global class ParkServiceMock implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
        // start - specify the response you want to send
        ParkService.byCountryResponse response_x = 
            new ParkService.byCountryResponse();
        response_x.return_x = new String[]{'a','b','c'};
        // end
        response.put('response_x', response_x); 
   }
}



The Apex classes created by the WSDL2Apex tool:
 
//Generated by wsdl2apex

public class ParkService {
    public class byCountryResponse {
        public String[] return_x;
        private String[] return_x_type_info = new String[]{'return','http://parks.services/',null,'0','-1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'return_x'};
    }
    public class byCountry {
        public String arg0;
        private String[] arg0_type_info = new String[]{'arg0','http://parks.services/',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://parks.services/','false','false'};
        private String[] field_order_type_info = new String[]{'arg0'};
    }
    public class ParksImplPort {
        public String endpoint_x = 'https://th-apex-soap-service.herokuapp.com/service/parks';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{'http://parks.services/', 'ParkService'};
        public String[] byCountry(String arg0) {
            ParkService.byCountry request_x = new ParkService.byCountry();
            request_x.arg0 = arg0;
            ParkService.byCountryResponse response_x;
            Map<String, ParkService.byCountryResponse> response_map_x = new Map<String, ParkService.byCountryResponse>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              '',
              'http://parks.services/',
              'byCountry',
              'http://parks.services/',
              'byCountryResponse',
              'ParkService.byCountryResponse'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.return_x;
        }
    }
}


And lastly, the parks.xml file itself:
 
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
 xmlns:tns="http://parks.services/"
 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
 name="ParksImplService" targetNamespace="http://parks.services/">
  <wsdl:types>
<xs:schema
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:tns="http://parks.services/"
 elementFormDefault="unqualified"
 targetNamespace="http://parks.services/"
 version="1.0">
  <xs:element name="byCountry" type="tns:byCountry"/>
  <xs:element name="byCountryResponse" type="tns:byCountryResponse"/>
  <xs:complexType name="byCountry">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="byCountryResponse">
    <xs:sequence>
      <xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>
  </wsdl:types>
  <wsdl:message name="byCountry">
    <wsdl:part element="tns:byCountry" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="byCountryResponse">
    <wsdl:part element="tns:byCountryResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="Parks">
    <wsdl:operation name="byCountry">
      <wsdl:input message="tns:byCountry" name="byCountry">
    </wsdl:input>
      <wsdl:output message="tns:byCountryResponse" name="byCountryResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="ParksImplServiceSoapBinding" type="tns:Parks">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="byCountry">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="byCountry">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="byCountryResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="ParksImplService">
    <wsdl:port binding="tns:ParksImplServiceSoapBinding" name="ParksImplPort">
      <soap:address location="https://th-apex-soap-service.herokuapp.com/service/parks"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>



I'm hoping that Mr Douglas is monitoring this post and can offer a reason why this error is persisting.  By the way, I've read a number of posts that pertain to errors that claim the absence of classes that appear to exist, in addition to posts that offer tips on clearing caches and re-running stuff.   So far, I haven't hit on any technique that solves the problem.  I refuse to get cocky and sugest that something in the system is broken, but for the life of me, I can't see what if anything I'm doing wrong.  I don't think I've messed up, but I "sit" ready to be corrected.  (:>)

David
MarcFogMarcFog
Hi David, before going through your code in detail (which looks fine at first glance),  try deleting your ParkServiceMock class once more, and when recreating it, manually type the name and do NOT cut/paste the name.  My apologies if this is what you already did.  This did the trick for me - I was consistently getting the same error and suspected a bug as well.  For some reason the cut/paste process seems to have incorporated different characters into the class name, causing the system to not detect the class. I found this helpful suggestion from another post. 
David Bailey 16David Bailey 16
Dear Mark,

Deleting the ParkServiceMock 'again' and then re-creating it a third time seems to have done it.  Guess third time IS a charm!  (:>)  In any case, thank you very much.  I love the Salesforce Trailhead challenges,*cough* when they work *cough*.  I also like the jokey banter.  The 'glitchy' encounters, not so much.  Again, thanks.  Cheers,

David
MarcFogMarcFog
Excellent!  I'm glad it helped.  
Jhonny Alexander Ramirez ChiroqueJhonny Alexander Ramirez Chiroque
A mi me ha funcionado este codigo
public class ParkLocator {
    public static List<String> Country(String name) {
        List<String> countries = new List<String>();
         ParkService.ParksImplPort park = new ParkService.ParksImplPort();
        countries = park.byCountry(name);
        return countries;
    }
}

----------------------------------------------------------------------------------------------------------

@isTest
private class ParkLocatorTest {
    @isTest static void testCallout() {              
        // This causes a fake response to be generated
        Test.setMock(WebServiceMock.class, new ParkServiceMock());
        // Call the method that invokes a callout
        String[] parks = ParkLocator.Country('Japan');
        // Verify that a fake result is returned
        system.assert(parks.size() > 0);
    }
}

----------------------------------------------------------------------------------------------------------

@isTest
global class ParkServiceMock implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
            // start - specify the response you want to send
            ParkService.byCountryResponse response_x = new ParkService.byCountryResponse();
               response_x.return_x = new List<String>{'Germany', 'India', 'Japan', 'United States'};
            response.put('response_x', response_x); 
   }
}