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);
    }
}
13
  • Best you post the relevant parts of your code - I have working tests that catch custom exceptions.
    – Keith C
    Sep 4, 2016 at 12:12
  • It's really strange, question will be updated in few minutes
    – misha_m
    Sep 4, 2016 at 12:14
  • When you say "stop and fail" what exactly does the test runner report?
    – Keith C
    Sep 4, 2016 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, 2016 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
    – misha_m
    Sep 4, 2016 at 16:40

1 Answer 1

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.

4
  • 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
    – misha_m
    Sep 4, 2016 at 12:58
  • my fault, I use throw new CustomException('message', ex); in code
    – misha_m
    Sep 4, 2016 at 13:03
  • And one more detail :) This send method must be marked as @Future(callout = true), sorry
    – misha_m
    Sep 4, 2016 at 13:11
  • Question updated
    – misha_m
    Sep 4, 2016 at 13:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .