2

Why I can't catch custom exception in test classes? If code throw custom exception, test immediatly fail.

System exceptions can be catched and handled in test methods without problems.

public class CustomException extends Exception {
}

This exception have 30 level API

public class MyClass {
    public void methodToTest() {
        // do something
        someMethod();
    }

    @Future(callout = true)
    private static void someMethod() { 
        try {
            ...
            httpClient.send(httpRequest);
            ...
        } catch (CustomException ex) {
            throw ex;
        } catch (Exception ex) {
            // some actions
            throw new CustomException('<message>', ex);
        }
    }
}

This class also have 30 level API

In test class I have 2 mocks (for HttpCallout)

First throw my Custom Exception and second throw CalloutException

In first case test immediatly stop and fail on line

            httpClient.send(httpRequest);       

In second case on line

            throw new CustomException('<message>', ex);

UPD. code:

public class MyClasss {

        public class CustomException extends Exception {
        }

        public void sendMethod() {
            String endPoint = 'endPoint';
            String body = 'body';
            send(endPoint, body);
        }

        @Future(callout=true)
        private static void send(String endPoint, String body) {
            try {
                 HttpRequest request =  new HttpRequest();
                request.setEndpoint('https://' + endPoint + '/');
                request.setMethod('POST');
                request.setHeader('Content-Type', 'application/json');
                request.setHeader('Content-Length', String.valueOf(Blob.valueOf(body).size()));
                request.setHeader('Accept', 'application/json');
                request.setBody(body);
                request.setTimeout(120000);

                new Http().send(request);
                System.assert(false);
            } catch (CustomException e) {
                throw e;
                System.assertEquals('error', e.getMessage());
            } catch (Exception e) {
                throw new CustomException('test', e);
            }
        }
    }

And test class

@IsTest
private class MyTest {



    private class Mock implements HttpCalloutMock {
        Boolean wasCalled = false;
        public HTTPResponse respond(HTTPRequest request) {
            wasCalled = true;
            throw new MyClasss.CustomException('error');
        }
    }



    @IsTest
    static void test() {
        Mock m = new Mock();
        Test.setMock(HttpCalloutMock.class, m);

        MyClasss instance = new MyClasss();
        Test.startTest();
        instance.sendMethod();
        Test.stopTest();
        System.assert(m.wasCalled);
    }
}
  • Best you post the relevant parts of your code - I have working tests that catch custom exceptions. – Keith C Sep 4 '16 at 12:12
  • It's really strange, question will be updated in few minutes – RasMisha Sep 4 '16 at 12:14
  • When you say "stop and fail" what exactly does the test runner report? – Keith C Sep 4 '16 at 12:29
  • Are you trying to test that the exception in your future method was thrown? If, I do not believe it will cause an exception that can be caught in your test as it is asynchronous after all. I could be wrong but outside of test it just prints the message in Alex jobs detail. The callout for api 30 will flat stop the test and never make it to an exception – Eric Sep 4 '16 at 16:34
  • In this case I think that all code between Test.startTest() and Test.stopTest() inlined (and performed synchronously), but I am mistaken. Thank you, @Eric – RasMisha Sep 4 '16 at 16:40
1

This (updated to include the @future) test - where a custom exception is caught - passes including when using API 30:

@IsTest
private class MyTest {

    private class CustomException extends Exception {
    }

    private class Mock implements HttpCalloutMock {
        Boolean wasCalled = false;
        public HTTPResponse respond(HTTPRequest request) {
            wasCalled = true;
            throw new CustomException('error');
        }
    }

    @Future(callout=true)
    private static void send() {
        try {
            new Http().send(new HttpRequest());
            System.assert(false);
        } catch (CustomException e) {
            System.assertEquals('error', e.getMessage());
        }
    }

    @IsTest
    static void test() {
        Mock m = new Mock();
        Test.setMock(HttpCalloutMock.class, m);
        Test.startTest();
        send();
        Test.stopTest();
        System.assert(m.wasCalled);
    }
}

Suggest you compare your logic with this to see what is different. Note that you must call Test.stopTest() to ensure that the @future call completes.

|improve this answer|||||
  • In dev.console I open and perform test. In tab Errors I have 'CustomException: <message>', in tab Stack Trace: MyClass.method: line 321, column 1 (where throw CustomException) Caused by Class.System.Type.newInstance: line 33, column 1 – RasMisha Sep 4 '16 at 12:58
  • my fault, I use throw new CustomException('message', ex); in code – RasMisha Sep 4 '16 at 13:03
  • And one more detail :) This send method must be marked as @Future(callout = true), sorry – RasMisha Sep 4 '16 at 13:11
  • Question updated – RasMisha Sep 4 '16 at 13:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.