Skip to content

Commit cd0cb55

Browse files
Created JUnitFailToAssertJFail visitor and tests (#28)
* Created JUnitFailToAssertJFail visitor and tests
1 parent 69a82d4 commit cd0cb55

File tree

2 files changed

+345
-0
lines changed

2 files changed

+345
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.java.testing.junitassertj;
17+
18+
import org.openrewrite.java.AutoFormat;
19+
import org.openrewrite.java.JavaIsoRefactorVisitor;
20+
import org.openrewrite.java.MethodMatcher;
21+
import org.openrewrite.java.RemoveUnusedImports;
22+
import org.openrewrite.java.tree.*;
23+
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
27+
import static org.openrewrite.Formatting.EMPTY;
28+
import static org.openrewrite.Formatting.format;
29+
import static org.openrewrite.Tree.randomId;
30+
import static org.openrewrite.java.tree.MethodTypeBuilder.newMethodType;
31+
32+
/**
33+
* This is a refactoring visitor that will convert JUnit-style fail() to assertJ's fail().
34+
*
35+
* This visitor only supports the migration of the following JUnit 5 fail() methods:
36+
*
37+
* <PRE>
38+
* fail() -> fail("")
39+
* fail(String message) -> fail(String message)
40+
* fail(String message, Throwable cause) -> fail(String message, Throwable cause)
41+
* fail(Throwable cause) -> fail("", Throwable cause)
42+
* </PRE>
43+
*
44+
* Note: There is an additional method signature in JUnit that accepts a StringSupplier as an argument. Attempts
45+
* to map this signature into assertJ's model obfuscates the original assertion.
46+
*/
47+
public class JUnitFailToAssertJFail extends JavaIsoRefactorVisitor {
48+
private static final String JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.junit.jupiter.api.Assertions";
49+
private static final String ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.assertj.core.api.Assertions";
50+
51+
/**
52+
* This matcher finds the junit methods that will be migrated by this visitor.
53+
*/
54+
private static final MethodMatcher JUNIT_FAIL_MATCHER = new MethodMatcher(
55+
JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME + " fail(..)"
56+
);
57+
58+
@Override
59+
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) {
60+
J.MethodInvocation original = method;
61+
if (!JUNIT_FAIL_MATCHER.matches(method)) {
62+
return original;
63+
}
64+
65+
MethodTypeBuilder methodTypeBuilder = newMethodType()
66+
.declaringClass(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME)
67+
.flags(Flag.Public, Flag.Static)
68+
.returnType(
69+
JavaType.Class.build("java.lang.Object"),
70+
new JavaType.GenericTypeVariable(
71+
"T",
72+
JavaType.Class.build("java.lang.Object")
73+
)
74+
)
75+
.name("fail");
76+
77+
List<Expression> originalArgs = original.getArgs().getArgs();
78+
List<Expression> newArgs = new ArrayList<>();
79+
80+
if(originalArgs.get(0) instanceof J.Literal) {
81+
newArgs.add(originalArgs.get(0));
82+
methodTypeBuilder.parameter(JavaType.Class.build("java.lang.String"), "failureMessage");
83+
84+
if(originalArgs.size() == 2) {
85+
newArgs.add(originalArgs.get(1));
86+
}
87+
} else if(originalArgs.get(0) instanceof J.Empty) {
88+
newArgs.add(J.Literal.buildString(""));
89+
} else {
90+
methodTypeBuilder.parameter(JavaType.Class.build("java.lang.String"), "failureMessage");
91+
methodTypeBuilder.parameter("java.lang.Throwable", "realCause");
92+
newArgs.add(J.Literal.buildString(""));
93+
newArgs.add(originalArgs.get(0));
94+
}
95+
96+
JavaType.Method assertJFailMethodType = methodTypeBuilder.build();
97+
98+
J.MethodInvocation assertJFail = new J.MethodInvocation(
99+
randomId(),
100+
null,
101+
null,
102+
J.Ident.build(randomId(), "fail", JavaType.Primitive.Void, EMPTY),
103+
new J.MethodInvocation.Arguments(
104+
randomId(),
105+
newArgs,
106+
EMPTY
107+
),
108+
assertJFailMethodType,
109+
format("\n")
110+
);
111+
112+
maybeAddImport(ASSERTJ_QUALIFIED_ASSERTIONS_CLASS_NAME, "fail");
113+
andThen(new RemoveUnusedImports());
114+
andThen(new AutoFormat(assertJFail));
115+
116+
return assertJFail;
117+
}
118+
}
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.java.testing.junitassertj
17+
18+
import org.junit.jupiter.api.Test
19+
import org.openrewrite.Parser
20+
import org.openrewrite.RefactorVisitor
21+
import org.openrewrite.RefactorVisitorTestForParser
22+
import org.openrewrite.java.JavaParser
23+
import org.openrewrite.java.tree.J
24+
25+
class JUnitFailToAssertJFailTest : RefactorVisitorTestForParser<J.CompilationUnit> {
26+
override val parser: Parser<J.CompilationUnit> = JavaParser.fromJavaVersion()
27+
.classpath("junit", "assertj-core", "apiguardian-api")
28+
.build()
29+
30+
override val visitors: Iterable<RefactorVisitor<*>> = listOf(JUnitFailToAssertJFail())
31+
32+
@Test
33+
fun singleStaticMethodNoMessage() = assertRefactored(
34+
before = """
35+
import org.junit.Test;
36+
37+
import static org.junit.jupiter.api.Assertions.fail;
38+
39+
public class A {
40+
41+
@Test
42+
public void test() {
43+
fail();
44+
}
45+
}
46+
""",
47+
after = """
48+
import org.junit.Test;
49+
50+
import static org.assertj.core.api.Assertions.fail;
51+
52+
public class A {
53+
54+
@Test
55+
public void test() {
56+
fail("");
57+
}
58+
}
59+
"""
60+
)
61+
62+
@Test
63+
fun singleStaticMethodWithMessage() = assertRefactored(
64+
before = """
65+
import org.junit.Test;
66+
67+
import static org.junit.jupiter.api.Assertions.fail;
68+
69+
public class A {
70+
71+
@Test
72+
public void test() {
73+
fail("This should fail");
74+
}
75+
}
76+
""",
77+
after = """
78+
import org.junit.Test;
79+
80+
import static org.assertj.core.api.Assertions.fail;
81+
82+
public class A {
83+
84+
@Test
85+
public void test() {
86+
fail("This should fail");
87+
}
88+
}
89+
"""
90+
)
91+
92+
@Test
93+
fun singleStaticMethodWithMessageAndCause() = assertRefactored(
94+
before = """
95+
import org.junit.Test;
96+
97+
import static org.junit.jupiter.api.Assertions.fail;
98+
99+
public class A {
100+
101+
@Test
102+
public void test() {
103+
Throwable t = new Throwable();
104+
fail("This should fail", t);
105+
}
106+
}
107+
""",
108+
after = """
109+
import org.junit.Test;
110+
111+
import static org.assertj.core.api.Assertions.fail;
112+
113+
public class A {
114+
115+
@Test
116+
public void test() {
117+
Throwable t = new Throwable();
118+
fail("This should fail", t);
119+
}
120+
}
121+
"""
122+
)
123+
124+
@Test
125+
fun singleStaticMethodWithCause() = assertRefactored(
126+
before = """
127+
import org.junit.Test;
128+
129+
import static org.junit.jupiter.api.Assertions.fail;
130+
131+
public class A {
132+
133+
@Test
134+
public void test() {
135+
Throwable t = new Throwable();
136+
fail(t);
137+
fail(new Throwable());
138+
}
139+
}
140+
""",
141+
after = """
142+
import org.junit.Test;
143+
144+
import static org.assertj.core.api.Assertions.fail;
145+
146+
public class A {
147+
148+
@Test
149+
public void test() {
150+
Throwable t = new Throwable();
151+
fail("",t);
152+
fail("",new Throwable());
153+
}
154+
}
155+
"""
156+
)
157+
158+
@Test
159+
fun inlineReference() = assertRefactored(
160+
before = """
161+
import org.junit.Test;
162+
163+
public class A {
164+
165+
@Test
166+
public void test() {
167+
org.junit.jupiter.api.Assertions.fail();
168+
org.junit.jupiter.api.Assertions.fail("This should fail");
169+
org.junit.jupiter.api.Assertions.fail("This should fail", new Throwable());
170+
org.junit.jupiter.api.Assertions.fail(new Throwable());
171+
}
172+
}
173+
""",
174+
after = """
175+
import org.junit.Test;
176+
177+
import static org.assertj.core.api.Assertions.fail;
178+
179+
public class A {
180+
181+
@Test
182+
public void test() {
183+
fail("");
184+
fail("This should fail");
185+
fail("This should fail", new Throwable());
186+
fail("",new Throwable());
187+
}
188+
}
189+
"""
190+
)
191+
192+
@Test
193+
fun mixedReferences() = assertRefactored(
194+
before = """
195+
import org.junit.Test;
196+
197+
import static org.junit.jupiter.api.Assertions.fail;
198+
199+
public class A {
200+
201+
@Test
202+
public void test() {
203+
fail();
204+
org.junit.jupiter.api.Assertions.fail("This should fail");
205+
fail("This should fail", new Throwable());
206+
org.junit.jupiter.api.Assertions.fail(new Throwable());
207+
}
208+
}
209+
""",
210+
after = """
211+
import org.junit.Test;
212+
213+
import static org.assertj.core.api.Assertions.fail;
214+
215+
public class A {
216+
217+
@Test
218+
public void test() {
219+
fail("");
220+
fail("This should fail");
221+
fail("This should fail", new Throwable());
222+
fail("",new Throwable());
223+
}
224+
}
225+
"""
226+
)
227+
}

0 commit comments

Comments
 (0)