diff --git a/subprojects/errorprone/src/main/java/org/mockito/errorprone/bugpatterns/MockitoMockedStatic.java b/subprojects/errorprone/src/main/java/org/mockito/errorprone/bugpatterns/MockitoMockedStatic.java new file mode 100644 index 0000000000..d22e5258b0 --- /dev/null +++ b/subprojects/errorprone/src/main/java/org/mockito/errorprone/bugpatterns/MockitoMockedStatic.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017 Mockito contributors + * This program is made available under the terms of the MIT License. + */ +package org.mockito.errorprone.bugpatterns; + +import com.google.auto.service.AutoService; +import com.google.errorprone.BugPattern; +import com.google.errorprone.BugPattern.SeverityLevel; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher; +import com.google.errorprone.matchers.Description; +import com.sun.source.tree.VariableTree; + +@AutoService(BugChecker.class) +@BugPattern( + name = "MockitoMockedStatic", + summary = "Fields or parameters annotated with @Mock in MockedStatic can lead to compilation issues.", + explanation = "Fields or parameters annotated with @Mock in MockedStatic can lead to compilation issues.", + severity = SeverityLevel.ERROR) +public class MockitoMockedStatic extends BugChecker implements VariableTreeMatcher { + + @Override + public Description matchVariable(VariableTree tree, VisitorState state) { + if (tree.getModifiers().getAnnotations().stream() + .anyMatch(annotation -> + state.getSourceForNode(annotation).equals("@org.mockito.Mock") + && state.getSourceForNode(tree.getType()).equals("org.mockito.MockedStatic"))) { + return describeMatch(tree); + } + + return Description.NO_MATCH; + } +} diff --git a/subprojects/errorprone/src/test/java/org/mockito/errorprone/bugpatterns/MockitoMockedStaticTest.java b/subprojects/errorprone/src/test/java/org/mockito/errorprone/bugpatterns/MockitoMockedStaticTest.java new file mode 100644 index 0000000000..44aa8d7c9f --- /dev/null +++ b/subprojects/errorprone/src/test/java/org/mockito/errorprone/bugpatterns/MockitoMockedStaticTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017 Mockito contributors + * This program is made available under the terms of the MIT License. + */ +package org.mockito.errorprone.bugpatterns; + +import com.google.errorprone.CompilationTestHelper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class MockitoMockedStaticTest { + + private CompilationTestHelper compilationTestHelper; + + @Before + public void setup() { + compilationTestHelper = + CompilationTestHelper.newInstance(MockitoMockedStatic.class, getClass()); + } + + @Test + public void mockedStaticWithMockField_shouldError() { + compilationTestHelper + .addSourceLines( + "input.java", + "import org.mockito.Mock;", + "import org.mockito.MockedStatic;", + "import org.mockito.Mockito;", + "class Test {", + " @Mock", + " private Object mock;", + " public void test() {", + " try (MockedStatic mockedStatic = Mockito.mockStatic(Object.class)) {", + " // Do something with the mock", + " }", + " }", + "}") + .doTest(); + } + + @Test + public void mockedStaticWithMockParameter_shouldError() { + compilationTestHelper + .addSourceLines( + "input.java", + "import org.mockito.Mock;", + "import org.mockito.MockedStatic;", + "import org.mockito.Mockito;", + "class Test {", + " public void test(@Mock Object mock) {", + " try (MockedStatic mockedStatic = Mockito.mockStatic(Object.class)) {", + " // Do something with the mock", + " }", + " }", + "}") + .doTest(); + } + + @Test + public void mockedStaticWithoutMock_shouldNotError() { + compilationTestHelper + .addSourceLines( + "input.java", + "import org.mockito.MockedStatic;", + "import org.mockito.Mockito;", + "class Test {", + " public void test() {", + " try (MockedStatic mockedStatic = Mockito.mockStatic(Object.class)) {", + " // Do something without a mock", + " }", + " }", + "}") + .doTest(); + } +}