rewrite-testing-frameworks icon indicating copy to clipboard operation
rewrite-testing-frameworks copied to clipboard

`JUnitAssertThrowsToAssertExceptionType` does not convert cases where `executable` is a variable

Open timtebeek opened this issue 1 year ago • 2 comments

What version of OpenRewrite are you using?

  • https://github.com/openrewrite/rewrite-testing-frameworks/releases/tag/v2.6.0

What is the smallest, simplest way to reproduce the problem?

import org.junit.jupiter.api.function.Executable;

import static org.junit.jupiter.api.Assertions.assertThrows;

public class SimpleExpectedExceptionTest {
    public void throwsExceptionWithSpecificType() {
        Executable executable = () -> {
            throw new NullPointerException();
        };
        assertThrows(NullPointerException.class, executable);
    }
}

What did you expect to see?

import org.assertj.core.api.ThrowableAssert.ThrowingCallable;

import static org.junit.jupiter.api.Assertions.assertThrows;

public class SimpleExpectedExceptionTest {
    public void throwsExceptionWithSpecificType() {
        ThrowingCallable executable = () -> {
            throw new NullPointerException();
        };
        assertThatExceptionOfType(NullPointerException.class).isThrownBy(executable);
    }
}

What did you see instead?

No change, as the recipe fails to match the case where the argument is a variable. https://github.com/openrewrite/rewrite-testing-frameworks/blob/7ba17bbbfb2c9f5437a377d4e022c101a31579e2/src/main/java/org/openrewrite/java/testing/assertj/JUnitAssertThrowsToAssertExceptionType.java#L68-L74

Additional context

As reported on

  • https://stackoverflow.com/q/78366075/53444

timtebeek avatar Apr 23 '24 18:04 timtebeek

I guess instead of setting executable to null if it’s not a Lambda or MemberReference, like this

J executable = mi.getArguments().get(1);
                if (executable instanceof J.Lambda) {
                    executable = ((J.Lambda) executable).withType(THROWING_CALLABLE_TYPE);
                } else if (executable instanceof J.MemberReference) {
                    executable = ((J.MemberReference) executable).withType(THROWING_CALLABLE_TYPE);
                } else {
                    executable = executable.withType(THROWING_CALLABLE_TYPE);
                }

the code now sets the type of executable directly. This allows variables to be used correctly. The withType(THROWING_CALLABLE_TYPE) method is applied to all types of Executable, ensuring the transformation applies universally and keeping the method signature and descriptions concise and relevant. This change should handle cases where the Executable is a variable in the assertThrows call.

What are your thoughts @timtebeek ??

Riyazul555 avatar Jun 30 '24 10:06 Riyazul555

We've had another look at this, but this seems harder than initially anticipated. We'd have to track assignments and change their type to make this work. Removing the good-first-issue label.

timtebeek avatar Aug 12 '24 16:08 timtebeek