RMIT
RMIT

Reputation: 19

Runtime exceptions in Java 8 function

I'm using Java 8 Functions and converters and have the following:

Main class

public final class MainClass {
    public MainClass(
            final Function<InputModel, OutputModel> businessLogic,
            final Converter<Input, InputModel> inputConverter,
            final Converter<OutputModel, Output> outputConverter) {
        this.businessLogic = requireNonNull(businessLogic, "businessLogic is null.");
        this.inputConverter = requireNonNull(inputConverter, "inputConverter is null.");
        this.outputConverter = requireNonNull(outputConverter, "outputConverter is null.");
    }

    /**
     * Request Handler.
     */
    public Output handleRequest(final Input input) {
        requireNonNull(input, "input is null.");

        log.info("input request: {}", input);

        try {
            return inputConverter
                    .andThen(businessLogic)
                    .andThen(outputConverter)
                    .apply(input);
        } catch (final Exception ex) {
            throw new InternalServiceException(ex.getMessage(), ex);
        }
    }
}

Unit test

public final class TestClass {

    @Mock
    private Function<InputModel, OutputModel> mockedBusinessLogic;

    @Mock
    private Converter<Input, InputModel> mockedInputConverter;

    @Mock
    private Converter<OutputModel, Output> mockedOutputConverter;

    private MainClass mainClass = new MainClass(mockedBusinessLogic, mockedInputConverter, mockedOutputConverter);

    @Test
    public void handleRequest_SHOULD_throwException_WHEN_inputConverter_throwsException() {
        final RuntimeException inputConverterException = new NullPointerException(EXCEPTION_MESSAGE);

        // what should I mock here? apply or convert.. apply for `Converter` seems to be deprecated.
        when(mockedInputConverter.convert(input))
                .thenThrow(inputConverterException);

        final Exception exception = assertThrows(
                InternalServiceException.class,
                () -> mainClass.handleRequest(input)
        );

        assertThat(exception.getMessage(), is(EXCEPTION_MESSAGE));
        assertThat(exception.getCause(), is(inputConverterException));
    }
}

The above assertions fail. I expect that if the inputConverter throws an exception, the catch block in handleRequest would wrap it to InternalServiceException, but it doesn't seem to be happening.

Any help? How do I actually write unit tests for handleRequest method? I want to test the behavior when either of inputConveter, businessLogic or outputConveter throws exception.

Upvotes: 0

Views: 149

Answers (1)

knittl
knittl

Reputation: 265546

Everything in your code is a mock. When you call andThen on your mocked inputConverter, then either null or a new mock instance is returned (depending on configuration). Each andThen will return a new instance with the chained converters (at least that is what I assume)

Make sure you mock all required methods, or better, use real objects instantiated from real classes.

Setting breakpoints and then debugging should help you find the issue. If you set in your try-block, and then single-step through the code, you will see that the way mocks are used in your code will not work. You could also save each result of andThen in a variable and then check in the debugger what type each has. I'm pretty sure it will either be null or "Mock for class X".

Upvotes: 1

Related Questions