Question:

How to create object by it's name?

Luca: 20 May 2022

I'm writing a REST service which calls external service. I want to write a test for my service. I came up with no possibility to mock this call as it's in managed package. I want to wrap this call with Test.isRunninTest() method. And here is the problem - I can't instantiate a result of this call because... This class doesn't have a constructor. So I want to instantiate it by it's name. Smth like:

System.Type t = mngdpckg.WebServiceClass.ResultSmthCoolExt.class; result = (mngdpckg.WebServiceClass.ResultSmthCoolExt)t.newInstance();

This code gives me

FATAL_ERROR|MyCoolService.Exception: Error processing transaction: mngdpckg.WebServiceClass.ResultSmthCoolExt does not have a no-arg constructor

Is there any chance I can get this class' instance in a test?

Answer:
Nova: 20 May 2022

You can only instantiate like this if you have a no arg constructor (https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_type.htm#apex_System_Type_newInstance).

If you did have such a constructor, the syntax would be:

Type t = Type.forName('mngdpckg.WebServiceClass.ResultSmthCoolExt');
result = t.newInstance();

However, you'll end up with the same error as you have stated you don't have a constructor.

From the docs:

Calling this method on a type corresponding to a class that has a private no-argument constructor results in a System.TypeException, as expected because the type can’t be instantiated. For Apex saved using Salesforce.com API version 28.0 and earlier, this method returns an instance of the class instead.

Which implies that classes on API <=28 will return an Instance, however on testing this:

public class TestNoArg {
    private TestNoArg() {}
}

Type t = Type.forName('TestNoArg');
t.newInstance();

I still get the exception:

System.TypeException: TestNoArg does not have a no-arg constructor