Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate JMockit Verifications to Mockito #540

Merged
merged 13 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class ArgumentMatchersRewriter {
}

private static final Map<JavaType.Primitive, String> PRIMITIVE_TO_MOCKITO_ARGUMENT_MATCHER = new HashMap<>();

static {
PRIMITIVE_TO_MOCKITO_ARGUMENT_MATCHER.put(JavaType.Primitive.Int, "anyInt");
PRIMITIVE_TO_MOCKITO_ARGUMENT_MATCHER.put(JavaType.Primitive.Long, "anyLong");
Expand All @@ -81,7 +82,7 @@ class ArgumentMatchersRewriter {
this.expectationsBlock = expectationsBlock;
}

J.Block rewriteExpectationsBlock() {
J.Block rewriteJMockitBlock() {
List<Statement> newStatements = new ArrayList<>(expectationsBlock.getStatements().size());
for (Statement expectationStatement : expectationsBlock.getStatements()) {
// for each statement, check if it's a method invocation and replace any argument matchers
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,31 @@
import org.openrewrite.java.tree.Statement;

import java.util.List;
import java.util.Optional;

@Value
@EqualsAndHashCode(callSuper = false)
public class JMockitExpectationsToMockito extends Recipe {
public class JMockitBlockToMockito extends Recipe {

@Override
public String getDisplayName() {
return "Rewrite JMockit Expectations";
return "Rewrite JMockit Expectations and Verifications";
}

@Override
public String getDescription() {
return "Rewrites JMockit `Expectations` blocks to Mockito statements.";
return "Rewrites JMockit `Expectations and Verifications` blocks to Mockito statements.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(new UsesType<>("mockit.Expectations", false),
new RewriteExpectationsVisitor());
return Preconditions.check(Preconditions.or(
new UsesType<>(JMockitBlockType.Expectations.getFqn(), false),
new UsesType<>(JMockitBlockType.Verifications.getFqn(), false)
), new RewriteJMockitBlockVisitor());
}

private static class RewriteExpectationsVisitor extends JavaIsoVisitor<ExecutionContext> {
private static class RewriteJMockitBlockVisitor extends JavaIsoVisitor<ExecutionContext> {

@Override
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDeclaration, ExecutionContext ctx) {
Expand All @@ -63,17 +67,19 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl
int bodyStatementIndex = 0;
// iterate over each statement in the method body, find Expectations blocks and rewrite them
while (bodyStatementIndex < statements.size()) {
if (!JMockitUtils.isValidExpectationsNewClassStatement(statements.get(bodyStatementIndex))) {
bodyStatementIndex += 1;
continue;
}
ExpectationsBlockRewriter ebr = new ExpectationsBlockRewriter(this, ctx, methodBody,
((J.NewClass) statements.get(bodyStatementIndex)), bodyStatementIndex);
methodBody = ebr.rewriteMethodBody();
statements = methodBody.getStatements();
// if the expectations rewrite failed, skip the next statement
if (ebr.isExpectationsRewriteFailed()) {
bodyStatementIndex += 1;
Statement s = statements.get(bodyStatementIndex);
Optional<JMockitBlockType> blockType = JMockitUtils.getJMockitBlock(s);
if (blockType.isPresent()) {
JMockitBlockRewriter blockRewriter = new JMockitBlockRewriter(this, ctx, methodBody,
((J.NewClass) s), bodyStatementIndex, blockType.get());
methodBody = blockRewriter.rewriteMethodBody();
statements = methodBody.getStatements();
// if the expectations rewrite failed, skip the next statement
if (blockRewriter.isRewriteFailed()) {
bodyStatementIndex++;
}
} else {
bodyStatementIndex++;
}
}
return md.withBody(methodBody);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.java.testing.jmockit;
timtebeek marked this conversation as resolved.
Show resolved Hide resolved

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Getter
enum JMockitBlockType {

Expectations("mockit.Expectations"),
Verifications("mockit.Verifications"); // Add NonStrictExpectations later

private final String fqn;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,32 @@
import org.openrewrite.java.tree.Statement;
import org.openrewrite.java.tree.TypeUtils;

import java.util.Optional;

import static java.util.Optional.empty;

class JMockitUtils {
static boolean isValidExpectationsNewClassStatement(Statement s) {

static Optional<JMockitBlockType> getJMockitBlock(Statement s) {
if (!(s instanceof J.NewClass)) {
return false;
return empty();
}
J.NewClass nc = (J.NewClass) s;
if (!(nc.getClazz() instanceof J.Identifier)) {
return false;
return empty();
}
J.Identifier clazz = (J.Identifier) nc.getClazz();
if (!TypeUtils.isAssignableTo("mockit.Expectations", clazz.getType())) {
return false;

// JMockit block should be composed of a block within another block
if (nc.getBody() == null || nc.getBody().getStatements().size() != 1) {
return empty();
}

for (JMockitBlockType blockType : JMockitBlockType.values()) {
if (TypeUtils.isAssignableTo(blockType.getFqn(), clazz.getType())) {
return Optional.of(blockType);
}
}
// Expectations block should be composed of a block within another block
return nc.getBody() != null && nc.getBody().getStatements().size() == 1;
return empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class SetupStatementsRewriter {

J.Block rewriteMethodBody() {
List<Statement> statements = methodBody.getStatements();
// iterate over each statement in the method body, find Expectations blocks and rewrite them
// iterate over each statement in the method body, find JMockit blocks and rewrite them
for (Statement s : statements) {
if (!JMockitUtils.isValidExpectationsNewClassStatement(s)) {
if (!JMockitUtils.getJMockitBlock(s).isPresent()) {
continue;
}
J.NewClass nc = (J.NewClass) s;
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/META-INF/rewrite/jmockit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ tags:
- testing
- jmockit
recipeList:
- org.openrewrite.java.testing.jmockit.JMockitExpectationsToMockito
- org.openrewrite.java.testing.jmockit.JMockitBlockToMockito
- org.openrewrite.java.testing.jmockit.JMockitAnnotatedArgumentToMockito
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: mockit.Mocked
Expand Down
Loading