├── .gitattributes ├── settings.gradle ├── .gitignore ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── ide.gradle ├── reproducible.gradle ├── shipkit.gradle └── java-publication.gradle ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── src ├── test │ └── java │ │ └── org │ │ └── mockitousage │ │ └── testng │ │ ├── SomeType.java │ │ ├── StrictStubsCode.java │ │ ├── ParentTest.java │ │ ├── failuretests │ │ ├── HasUnusedStubs.java │ │ ├── FailingOnPurposeBecauseIncorrectAnnotationUsage.java │ │ ├── FailingOnPurposeBecauseIncorrectStubbingSyntax.java │ │ ├── HasUnusedStubsInSetup.java │ │ ├── FailingOnPurposeBecauseWrongStubbingSyntaxInConfigurationMethod.java │ │ └── TestNGShouldFailWhenMockitoListenerFailsTest.java │ │ ├── ResetMocksInParentTestClassTooTest.java │ │ ├── InitializeChildTestWhenParentHasListenerTest.java │ │ ├── ConfigurationMethodTest.java │ │ ├── StrictnessWarnTest.java │ │ ├── EnsureMocksAreNotInitializedBeforeBeforeTestMethodTest.java │ │ ├── EnsureMocksAreNotInitializedBeforeBeforeClassMethodTest.java │ │ ├── EnsureMocksAreNotInitializedBeforeBeforeSuiteMethodTest.java │ │ ├── EnsureMocksAreNotInitializedBeforeBeforeGroupsMethodTest.java │ │ ├── TestWithoutListenerShouldNotInitializeAnnotatedFieldsTest.java │ │ ├── StaticMockTest.java │ │ ├── DontResetMocksIfNoListenerTest.java │ │ ├── AnnotatedFieldsShouldBeInitializedByMockitoTestNGListenerTest.java │ │ ├── CaptorAnnotatedFieldShouldBeClearedTest.java │ │ ├── InjectMocksTest.java │ │ ├── MockFieldsShouldBeResetBetweenTestMethodsTest.java │ │ ├── InjectMocksWithConstructorAndFinalTest.java │ │ ├── StrictStubsTest.java │ │ └── utils │ │ └── TestNGRunner.java └── main │ └── java │ └── org │ └── mockito │ └── testng │ ├── MockitoSettings.java │ └── MockitoTestNGListener.java ├── check_reproducibility.sh ├── LICENSE ├── docs └── release-notes.md ├── gradlew.bat ├── README.md └── gradlew /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bat text eol=crlf 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'mockito-testng' -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .gradle 3 | .idea 4 | *.ipr 5 | *.iml 6 | *.iws -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mockito/mockito-testng/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/ide.gradle: -------------------------------------------------------------------------------- 1 | assert rootProject == project 2 | 3 | allprojects { 4 | apply plugin: 'idea' 5 | } 6 | 7 | idea.project.vcs = 'Git' 8 | -------------------------------------------------------------------------------- /gradle/reproducible.gradle: -------------------------------------------------------------------------------- 1 | tasks.withType(AbstractArchiveTask) { 2 | preserveFileTimestamps = false 3 | reproducibleFileOrder = true 4 | } 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: "gradle" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/SomeType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class SomeType { 11 | List list; 12 | Map map; 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/StrictStubsCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * According to https://github.com/mockito/mockito/pull/1539 11 | */ 12 | public class StrictStubsCode { 13 | 14 | static void testStrictStubs(List list, String value) { 15 | list.add(value); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/ParentTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import org.mockito.Mock; 8 | import org.mockito.testng.MockitoTestNGListener; 9 | import org.testng.annotations.Listeners; 10 | 11 | import java.util.Map; 12 | 13 | @Listeners(MockitoTestNGListener.class) 14 | public abstract class ParentTest { 15 | 16 | @Mock Map parentMockField; 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/failuretests/HasUnusedStubs.java: -------------------------------------------------------------------------------- 1 | package org.mockitousage.testng.failuretests; 2 | 3 | import org.mockito.Mock; 4 | import org.mockito.testng.MockitoTestNGListener; 5 | import org.testng.annotations.Listeners; 6 | import org.testng.annotations.Test; 7 | 8 | import java.util.List; 9 | 10 | import static org.mockito.Mockito.when; 11 | 12 | @Listeners(MockitoTestNGListener.class) 13 | @Test(description = "Always failing, shouldn't be listed in 'mockito-testng.xml'") 14 | public class HasUnusedStubs { 15 | @Mock 16 | List mock; 17 | @Test public void test() { 18 | when(mock.add("a")).thenReturn(true); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /check_reproducibility.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # This script is taken from https://github.com/junit-team/junit5/pull/2217 4 | 5 | rm -rf checksums/ 6 | mkdir checksums/ 7 | 8 | export SOURCE_DATE_EPOCH=$(date +%s) 9 | 10 | function calculate_checksums() { 11 | OUTPUT=checksums/$1 12 | 13 | ./gradlew --no-build-cache clean assemble 14 | 15 | find ./build -name '*.jar' \ 16 | | grep '/build/libs/' \ 17 | | grep --invert-match 'javadoc' \ 18 | | sort \ 19 | | xargs sha256sum > ${OUTPUT} 20 | } 21 | 22 | 23 | calculate_checksums checksums-1.txt 24 | calculate_checksums checksums-2.txt 25 | 26 | diff checksums/checksums-1.txt checksums/checksums-2.txt 27 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/ResetMocksInParentTestClassTooTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.mockito.Mockito.verifyNoInteractions; 8 | 9 | import org.testng.annotations.Test; 10 | 11 | public class ResetMocksInParentTestClassTooTest extends ParentTest { 12 | 13 | @Test 14 | public void interact_with_parent_mock() throws Exception { 15 | parentMockField.get("a"); 16 | } 17 | 18 | @Test 19 | public void verify__zero_interaction_with_parent_mock() throws Exception { 20 | verifyNoInteractions(parentMockField); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/InitializeChildTestWhenParentHasListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import org.mockito.Mock; 8 | import org.testng.annotations.Test; 9 | 10 | import java.util.Map; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | public class InitializeChildTestWhenParentHasListenerTest extends ParentTest { 15 | 16 | @Mock Map childMockField; 17 | 18 | @Test 19 | @SuppressWarnings("unchecked") 20 | public void verify_mocks_are_initialized() { 21 | assertThat(childMockField).isNotNull(); 22 | assertThat(parentMockField).isNotNull(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /gradle/shipkit.gradle: -------------------------------------------------------------------------------- 1 | //Plugin jars are added to the buildscript classpath in the root build.gradle file 2 | apply plugin: "org.shipkit.shipkit-auto-version" 3 | apply plugin: "org.shipkit.shipkit-changelog" 4 | apply plugin: "org.shipkit.shipkit-github-release" 5 | 6 | tasks.named("generateChangelog") { 7 | previousRevision = project.ext.'shipkit-auto-version.previous-tag' 8 | githubToken = System.getenv("GITHUB_TOKEN") 9 | repository = "mockito/mockito-testng" 10 | } 11 | 12 | tasks.named("githubRelease") { 13 | def genTask = tasks.named("generateChangelog").get() 14 | dependsOn genTask 15 | repository = genTask.repository 16 | changelog = genTask.outputFile 17 | githubToken = System.getenv("GITHUB_TOKEN") 18 | newTagRevision = System.getenv("GITHUB_SHA") 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/failuretests/FailingOnPurposeBecauseIncorrectAnnotationUsage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng.failuretests; 6 | 7 | import org.mockito.Mock; 8 | import org.mockito.Spy; 9 | import org.mockito.testng.MockitoTestNGListener; 10 | import org.testng.annotations.Listeners; 11 | import org.testng.annotations.Test; 12 | 13 | import java.util.Map; 14 | 15 | /** 16 | * Should fail. 17 | * 18 | * @see TestNGShouldFailWhenMockitoListenerFailsTest 19 | */ 20 | @Listeners(MockitoTestNGListener.class) 21 | @Test(description = "Always failing, shouldn't be listed in 'mockito-testng.xml'") 22 | public class FailingOnPurposeBecauseIncorrectAnnotationUsage { 23 | @Mock @Spy Map cant_mock_and_spy_at_the_same_time; 24 | @Test public void dummy_test_method() throws Exception { } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/failuretests/FailingOnPurposeBecauseIncorrectStubbingSyntax.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng.failuretests; 6 | 7 | import static org.mockito.ArgumentMatchers.anySet; 8 | import static org.mockito.ArgumentMatchers.anyString; 9 | 10 | import org.mockito.testng.MockitoTestNGListener; 11 | import org.testng.annotations.Listeners; 12 | import org.testng.annotations.Test; 13 | 14 | /** 15 | * Should fail. 16 | * 17 | * @see TestNGShouldFailWhenMockitoListenerFailsTest 18 | */ 19 | @Listeners(MockitoTestNGListener.class) 20 | @Test(description = "Always failing, shouldn't be listed in 'mockito-testng.xml'") 21 | public class FailingOnPurposeBecauseIncorrectStubbingSyntax { 22 | 23 | public void incorrect_stubbing_syntax_in_test() { 24 | anyString(); 25 | anySet(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/ConfigurationMethodTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import org.mockito.Mock; 8 | import org.mockito.testng.MockitoTestNGListener; 9 | import org.testng.annotations.BeforeMethod; 10 | import org.testng.annotations.Listeners; 11 | import org.testng.annotations.Test; 12 | 13 | import java.util.Map; 14 | 15 | import static org.assertj.core.api.Assertions.assertThat; 16 | import static org.mockito.Mockito.when; 17 | 18 | @Listeners(MockitoTestNGListener.class) 19 | public class ConfigurationMethodTest { 20 | @Mock private Map map; 21 | 22 | @BeforeMethod 23 | public void some_behavior() { 24 | when(map.get("a")).thenReturn(1); 25 | } 26 | 27 | @Test 28 | public void mocks_should_stay_configured_with_behavior() { 29 | assertThat(map.get("a")).isEqualTo(1); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/failuretests/HasUnusedStubsInSetup.java: -------------------------------------------------------------------------------- 1 | package org.mockitousage.testng.failuretests; 2 | 3 | import java.util.List; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | import static org.mockito.Mockito.when; 7 | 8 | import org.mockito.Mock; 9 | import org.mockito.testng.MockitoTestNGListener; 10 | import org.testng.annotations.BeforeMethod; 11 | import org.testng.annotations.Listeners; 12 | import org.testng.annotations.Test; 13 | 14 | @Listeners(MockitoTestNGListener.class) 15 | public class HasUnusedStubsInSetup { 16 | 17 | @Mock 18 | List mock; 19 | 20 | @BeforeMethod 21 | public void setup() { 22 | when(mock.add("a")).thenReturn(true); 23 | } 24 | 25 | @Test(priority = 1) 26 | public void testPass() { 27 | assertThat(mock.add("a")).isTrue(); 28 | } 29 | 30 | @Test(priority = 2) 31 | public void testFail() { 32 | // stub from setup is not used 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/StrictnessWarnTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.mockito.Mockito.when; 8 | 9 | import java.util.List; 10 | 11 | import org.mockito.Mock; 12 | import org.mockito.quality.Strictness; 13 | import org.mockito.testng.MockitoSettings; 14 | import org.mockito.testng.MockitoTestNGListener; 15 | import org.testng.annotations.BeforeMethod; 16 | import org.testng.annotations.Listeners; 17 | import org.testng.annotations.Test; 18 | 19 | @Listeners(MockitoTestNGListener.class) 20 | @MockitoSettings(strictness = Strictness.WARN) 21 | public class StrictnessWarnTest { 22 | 23 | @Mock 24 | private List list; 25 | 26 | @BeforeMethod 27 | void setup() { 28 | when(list.add("a")).thenReturn(true); 29 | } 30 | 31 | @Test 32 | void not_used_stub_generate_warn() { 33 | // 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/mockito/testng/MockitoSettings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockito.testng; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Inherited; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.RetentionPolicy; 12 | import java.lang.annotation.Target; 13 | 14 | import org.mockito.quality.Strictness; 15 | 16 | /** 17 | * Annotation that can configure Mockito settings. Used by {@link MockitoTestNGListener} 18 | */ 19 | @Inherited 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ElementType.TYPE}) 22 | @Documented 23 | public @interface MockitoSettings { 24 | 25 | /** 26 | * Configure the strictness used in this test. 27 | * 28 | * @return The strictness to configure, by default {@link Strictness#STRICT_STUBS} 29 | */ 30 | Strictness strictness() default Strictness.STRICT_STUBS; 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/EnsureMocksAreNotInitializedBeforeBeforeTestMethodTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | import java.util.Observer; 10 | 11 | import org.mockito.Mock; 12 | import org.mockito.testng.MockitoTestNGListener; 13 | import org.testng.annotations.BeforeTest; 14 | import org.testng.annotations.Listeners; 15 | import org.testng.annotations.Test; 16 | 17 | @Listeners(MockitoTestNGListener.class) 18 | public class EnsureMocksAreNotInitializedBeforeBeforeTestMethodTest { 19 | 20 | @Mock 21 | Observer observer; 22 | 23 | @BeforeTest 24 | private void make_sure_mock_is_not_initialized() { 25 | assertThat(observer).isNull(); 26 | } 27 | 28 | @Test 29 | public void dummy_test1() { 30 | assertThat(observer).isNotNull(); 31 | } 32 | 33 | @Test 34 | public void dummy_test2() { 35 | assertThat(observer).isNotNull(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/EnsureMocksAreNotInitializedBeforeBeforeClassMethodTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | import java.util.Observer; 10 | 11 | import org.mockito.Mock; 12 | import org.mockito.testng.MockitoTestNGListener; 13 | import org.testng.annotations.BeforeClass; 14 | import org.testng.annotations.Listeners; 15 | import org.testng.annotations.Test; 16 | 17 | @Listeners(MockitoTestNGListener.class) 18 | public class EnsureMocksAreNotInitializedBeforeBeforeClassMethodTest { 19 | 20 | @Mock 21 | Observer observer; 22 | 23 | @BeforeClass 24 | private void make_sure_mock_is_not_initialized() { 25 | assertThat(observer).isNull(); 26 | } 27 | 28 | @Test 29 | public void dummy_test1() { 30 | assertThat(observer).isNotNull(); 31 | } 32 | 33 | @Test 34 | public void dummy_test2() { 35 | assertThat(observer).isNotNull(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/EnsureMocksAreNotInitializedBeforeBeforeSuiteMethodTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | import java.util.Observer; 10 | 11 | import org.mockito.Mock; 12 | import org.mockito.testng.MockitoTestNGListener; 13 | import org.testng.annotations.BeforeSuite; 14 | import org.testng.annotations.Listeners; 15 | import org.testng.annotations.Test; 16 | 17 | @Listeners(MockitoTestNGListener.class) 18 | public class EnsureMocksAreNotInitializedBeforeBeforeSuiteMethodTest { 19 | 20 | @Mock 21 | Observer observer; 22 | 23 | @BeforeSuite 24 | private void make_sure_mock_is_not_initialized() { 25 | assertThat(observer).isNull(); 26 | } 27 | 28 | @Test 29 | public void dummy_test1() { 30 | assertThat(observer).isNotNull(); 31 | } 32 | 33 | @Test 34 | public void dummy_test2() { 35 | assertThat(observer).isNotNull(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/EnsureMocksAreNotInitializedBeforeBeforeGroupsMethodTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | import java.util.Observer; 10 | 11 | import org.mockito.Mock; 12 | import org.mockito.testng.MockitoTestNGListener; 13 | import org.testng.annotations.BeforeGroups; 14 | import org.testng.annotations.Listeners; 15 | import org.testng.annotations.Test; 16 | 17 | @Listeners(MockitoTestNGListener.class) 18 | public class EnsureMocksAreNotInitializedBeforeBeforeGroupsMethodTest { 19 | 20 | @Mock 21 | Observer observer; 22 | 23 | @BeforeGroups 24 | private void make_sure_mock_is_not_initialized() { 25 | assertThat(observer).isNull(); 26 | } 27 | 28 | @Test 29 | public void dummy_test1() { 30 | assertThat(observer).isNotNull(); 31 | } 32 | 33 | @Test 34 | public void dummy_test2() { 35 | assertThat(observer).isNotNull(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/TestWithoutListenerShouldNotInitializeAnnotatedFieldsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import org.mockito.ArgumentCaptor; 8 | import org.mockito.Captor; 9 | import org.mockito.InjectMocks; 10 | import org.mockito.Mock; 11 | import org.mockito.Spy; 12 | import org.testng.annotations.Test; 13 | 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | import static org.assertj.core.api.Assertions.assertThat; 18 | 19 | public class TestWithoutListenerShouldNotInitializeAnnotatedFieldsTest { 20 | 21 | @Mock List list; 22 | @Spy Map map; 23 | @InjectMocks SomeType someType; 24 | @Captor ArgumentCaptor> captor; 25 | 26 | @Test 27 | public void test_not_annotated_by_MockitoTestNGListener_should_not_touch_annotated_fields() throws Exception { 28 | assertThat(list).isNull(); 29 | assertThat(map).isNull(); 30 | assertThat(captor).isNull(); 31 | assertThat(someType).isNull(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2020 Mockito contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/StaticMockTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | import org.mockito.Mock; 10 | import org.mockito.MockedStatic; 11 | import org.mockito.testng.MockitoTestNGListener; 12 | import org.testng.annotations.Listeners; 13 | import org.testng.annotations.Test; 14 | 15 | @Listeners(MockitoTestNGListener.class) 16 | public class StaticMockTest { 17 | 18 | static class Dummy { 19 | static String foo() { 20 | return "foo"; 21 | } 22 | } 23 | 24 | @Mock 25 | private MockedStatic dummy; 26 | 27 | @Test 28 | public void simple_static_mock() { 29 | assertThat(Dummy.foo()).isNull(); 30 | } 31 | 32 | @Test 33 | public void verify_static_method() { 34 | // given 35 | dummy.when(Dummy::foo).thenReturn("bar"); 36 | 37 | // when 38 | assertThat(Dummy.foo()).isEqualTo("bar"); 39 | 40 | // then 41 | dummy.verify(Dummy::foo); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/failuretests/FailingOnPurposeBecauseWrongStubbingSyntaxInConfigurationMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng.failuretests; 6 | 7 | import static org.mockito.ArgumentMatchers.anyString; 8 | 9 | import org.mockito.Mock; 10 | import org.mockito.testng.MockitoTestNGListener; 11 | import org.testng.annotations.BeforeMethod; 12 | import org.testng.annotations.Listeners; 13 | import org.testng.annotations.Test; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * Should fail. 19 | * 20 | * @see TestNGShouldFailWhenMockitoListenerFailsTest 21 | */ 22 | @Listeners(MockitoTestNGListener.class) 23 | @Test(description = "Always failing, shouldn't be listed in 'mockito-testng.xml'") 24 | public class FailingOnPurposeBecauseWrongStubbingSyntaxInConfigurationMethod { 25 | 26 | @Mock List list; 27 | 28 | // should fail 29 | @BeforeMethod public void some_wrong_stubs() { 30 | anyString(); 31 | } 32 | 33 | 34 | @Test 35 | public void here_to_execute_the_config_method() { 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/DontResetMocksIfNoListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import org.mockito.Mock; 8 | import org.mockito.MockitoAnnotations; 9 | import org.testng.annotations.BeforeMethod; 10 | import org.testng.annotations.Test; 11 | 12 | import java.io.IOException; 13 | import java.util.Map; 14 | 15 | import static org.assertj.core.api.Assertions.assertThat; 16 | import static org.mockito.Mockito.when; 17 | 18 | public class DontResetMocksIfNoListenerTest { 19 | 20 | @Mock private Map map; 21 | 22 | @BeforeMethod 23 | public void init_mocks() { 24 | MockitoAnnotations.initMocks(this); 25 | when(map.get("the answer to ...")).thenReturn(42); 26 | } 27 | 28 | @Test 29 | public void mock_behavior_not_resetted_1() throws IOException { 30 | assertThat(map.get("the answer to ...")).isEqualTo(42); 31 | } 32 | 33 | @Test 34 | public void mock_behavior_not_resetted_2() throws IOException { 35 | assertThat(map.get("the answer to ...")).isEqualTo(42); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/AnnotatedFieldsShouldBeInitializedByMockitoTestNGListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import org.mockito.ArgumentCaptor; 8 | import org.mockito.Captor; 9 | import org.mockito.InjectMocks; 10 | import org.mockito.Mock; 11 | import org.mockito.Spy; 12 | import org.mockito.testng.MockitoTestNGListener; 13 | import org.testng.annotations.Listeners; 14 | import org.testng.annotations.Test; 15 | 16 | import java.util.HashMap; 17 | import java.util.List; 18 | 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | 21 | @Listeners(MockitoTestNGListener.class) 22 | public class AnnotatedFieldsShouldBeInitializedByMockitoTestNGListenerTest { 23 | 24 | @Mock List list; 25 | @Spy HashMap map; 26 | @InjectMocks SomeType someType; 27 | @Captor ArgumentCaptor> captor; 28 | 29 | @Test 30 | public void ensure_annotated_fields_are_instantiated() throws Exception { 31 | assertThat(list).isNotNull(); 32 | assertThat(map).isNotNull(); 33 | assertThat(captor).isNotNull(); 34 | assertThat(someType).isNotNull(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/CaptorAnnotatedFieldShouldBeClearedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import org.mockito.ArgumentCaptor; 8 | import org.mockito.Captor; 9 | import org.mockito.Mock; 10 | import org.mockito.testng.MockitoTestNGListener; 11 | import org.testng.annotations.Listeners; 12 | import org.testng.annotations.Test; 13 | 14 | import java.util.List; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | import static org.mockito.Mockito.times; 18 | import static org.mockito.Mockito.verify; 19 | 20 | @Listeners(MockitoTestNGListener.class) 21 | public class CaptorAnnotatedFieldShouldBeClearedTest { 22 | 23 | @Captor ArgumentCaptor captor; 24 | @Mock List list; 25 | 26 | @Test 27 | public void first_test_method_that_uses_captor() throws Exception { 28 | list.add("a"); 29 | list.add("b"); 30 | 31 | verify(list, times(2)).add(captor.capture()); 32 | assertThat(captor.getAllValues()).containsOnly("a", "b"); 33 | } 34 | 35 | @Test 36 | public void second_test_method_that_uses_captor() throws Exception { 37 | list.add("t"); 38 | list.add("u"); 39 | 40 | verify(list, times(2)).add(captor.capture()); 41 | assertThat(captor.getAllValues()).containsOnly("t", "u"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/failuretests/TestNGShouldFailWhenMockitoListenerFailsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng.failuretests; 6 | 7 | import org.mockito.exceptions.base.MockitoException; 8 | import org.mockito.exceptions.misusing.InvalidUseOfMatchersException; 9 | import org.mockitousage.testng.utils.TestNGRunner; 10 | import org.testng.annotations.Test; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | @Test( 15 | singleThreaded = true, 16 | description = "Test that failing tests report a Mockito exception" 17 | ) 18 | public class TestNGShouldFailWhenMockitoListenerFailsTest { 19 | 20 | private final TestNGRunner runner = new TestNGRunner(); 21 | 22 | public void report_failure_on_incorrect_annotation_usage() { 23 | //when 24 | TestNGRunner.Result result = runner.run(FailingOnPurposeBecauseIncorrectAnnotationUsage.class); 25 | 26 | //then 27 | assertThat(result.getFailure()).isInstanceOf(MockitoException.class); 28 | } 29 | 30 | @Test 31 | public void report_failure_on_incorrect_stubbing_syntax_with_matchers_in_test_methods() { 32 | //when 33 | TestNGRunner.Result result = runner.run(FailingOnPurposeBecauseIncorrectStubbingSyntax.class); 34 | 35 | //then 36 | assertThat(result.getFailure()).isInstanceOf(InvalidUseOfMatchersException.class); 37 | } 38 | 39 | @Test 40 | public void report_failure_on_incorrect_stubbing_syntax_with_matchers_in_configuration_methods() throws Exception { 41 | //when 42 | TestNGRunner.Result result = runner.run(FailingOnPurposeBecauseWrongStubbingSyntaxInConfigurationMethod.class); 43 | 44 | //then 45 | assertThat(result.getFailure()).isInstanceOf(InvalidUseOfMatchersException.class); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/InjectMocksTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.mockito.Mockito.times; 9 | import static org.mockito.Mockito.verify; 10 | import static org.mockito.Mockito.when; 11 | 12 | import java.util.Random; 13 | 14 | import org.mockito.InjectMocks; 15 | import org.mockito.Mock; 16 | import org.mockito.testng.MockitoTestNGListener; 17 | import org.testng.annotations.Listeners; 18 | import org.testng.annotations.Test; 19 | 20 | @Listeners(MockitoTestNGListener.class) 21 | public class InjectMocksTest { 22 | 23 | interface Client { 24 | int aMethod(); 25 | } 26 | 27 | static class Service { 28 | Client client; 29 | 30 | int callClient() { 31 | return client.aMethod(); 32 | } 33 | } 34 | 35 | @Mock 36 | private Client client; 37 | 38 | @InjectMocks 39 | private Service service; 40 | 41 | private int lastClientHash = 0; 42 | 43 | @Test(invocationCount = 4) 44 | void inject_mock_should_be_refreshed() { 45 | 46 | // we have correct injected mock 47 | assertThat(client).isNotNull(); 48 | assertThat(service.client).isNotNull().isSameAs(client); 49 | 50 | // we have new mock 51 | assertThat(lastClientHash).isNotEqualTo(client.hashCode()); 52 | 53 | // clear mock 54 | assertThat(service.callClient()).isZero(); 55 | 56 | // make some stub 57 | int i = new Random().nextInt() + 1; 58 | when(client.aMethod()).thenReturn(i); 59 | 60 | // and test it 61 | assertThat(service.callClient()).isEqualTo(i); 62 | 63 | verify(client, times(2)).aMethod(); 64 | 65 | // remember last mock hash 66 | lastClientHash = client.hashCode(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/MockFieldsShouldBeResetBetweenTestMethodsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import org.mockito.InjectMocks; 8 | import org.mockito.Mock; 9 | import org.mockito.Spy; 10 | import org.mockito.testng.MockitoTestNGListener; 11 | import org.testng.annotations.Listeners; 12 | import org.testng.annotations.Test; 13 | 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Observable; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | import static org.mockito.ArgumentMatchers.anyString; 20 | import static org.mockito.BDDMockito.given; 21 | import static org.mockito.Mockito.never; 22 | import static org.mockito.Mockito.verify; 23 | 24 | @Listeners(MockitoTestNGListener.class) 25 | public class MockFieldsShouldBeResetBetweenTestMethodsTest { 26 | 27 | @Mock List list; 28 | @Spy HashMap hashMap; 29 | @InjectMocks SomeType someType; 30 | 31 | @Mock Observable will_be_nulled; 32 | 33 | @Test 34 | public void behaviour_A_without_infection_from_behaviour_B() { 35 | // verify mock is clean 36 | assertThat(list.get(0)).isNull(); 37 | verify(list, never()).add(anyString()); 38 | 39 | // local behaviour A 40 | given(list.get(0)).willReturn("A"); 41 | assertThat(list.get(0)).isEqualTo("A"); 42 | 43 | list.add("something else after A"); 44 | } 45 | 46 | @Test 47 | public void behaviour_B_without_infection_from_behaviour_A() { 48 | // verify mock is clean 49 | assertThat(list.get(0)).isNull(); 50 | verify(list, never()).add(anyString()); 51 | 52 | // local behaviour A 53 | given(list.get(0)).willReturn("B"); 54 | assertThat(list.get(0)).isEqualTo("B"); 55 | 56 | list.add("something else after B"); 57 | } 58 | 59 | @Test 60 | public void dont_fail_when_reseting_null_field() { 61 | will_be_nulled = null; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/InjectMocksWithConstructorAndFinalTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | import static org.mockito.Mockito.times; 9 | import static org.mockito.Mockito.verify; 10 | import static org.mockito.Mockito.when; 11 | 12 | import java.util.Random; 13 | 14 | import org.mockito.InjectMocks; 15 | import org.mockito.Mock; 16 | import org.mockito.testng.MockitoTestNGListener; 17 | import org.testng.annotations.Listeners; 18 | import org.testng.annotations.Test; 19 | 20 | @Listeners(MockitoTestNGListener.class) 21 | public class InjectMocksWithConstructorAndFinalTest { 22 | 23 | interface Client { 24 | int aMethod(); 25 | } 26 | 27 | static class Service { 28 | final Client client; 29 | 30 | public Service(Client client) { 31 | this.client = client; 32 | } 33 | 34 | int callClient() { 35 | return client.aMethod(); 36 | } 37 | } 38 | 39 | @Mock 40 | private Client client; 41 | 42 | @InjectMocks 43 | private Service service; 44 | 45 | private int lastClientHash = 0; 46 | private int lastServiceHash = 0; 47 | 48 | 49 | @Test(invocationCount = 4) 50 | void inject_mock_should_be_refreshed() { 51 | 52 | // we have correct injected mock 53 | assertThat(client).isNotNull(); 54 | assertThat(service.client).isNotNull().isSameAs(client); 55 | 56 | // we have new mock 57 | assertThat(lastClientHash).isNotEqualTo(client.hashCode()); 58 | // we have new InjectMocks filed value 59 | assertThat(lastServiceHash).isNotEqualTo(service.hashCode()); 60 | 61 | // clear mock 62 | assertThat(service.callClient()).isZero(); 63 | 64 | // make some stub 65 | int i = new Random().nextInt() + 1; 66 | when(client.aMethod()).thenReturn(i); 67 | 68 | // and test it 69 | assertThat(service.callClient()).isEqualTo(i); 70 | 71 | verify(client, times(2)).aMethod(); 72 | 73 | // remember last mock and InjectMocks field hash 74 | lastClientHash = client.hashCode(); 75 | lastServiceHash = service.hashCode(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/StrictStubsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockitousage.testng; 6 | 7 | import java.util.List; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | import static org.mockito.Mockito.verifyNoMoreInteractions; 11 | import static org.mockito.Mockito.when; 12 | 13 | import org.assertj.core.api.Assertions; 14 | import org.mockito.Mock; 15 | import org.mockito.exceptions.misusing.PotentialStubbingProblem; 16 | import org.mockito.exceptions.misusing.UnnecessaryStubbingException; 17 | import org.mockito.testng.MockitoSettings; 18 | import org.mockito.testng.MockitoTestNGListener; 19 | import org.mockitousage.testng.failuretests.HasUnusedStubs; 20 | import org.mockitousage.testng.failuretests.HasUnusedStubsInSetup; 21 | import org.mockitousage.testng.utils.TestNGRunner; 22 | import org.testng.annotations.Listeners; 23 | import org.testng.annotations.Test; 24 | 25 | @Listeners(MockitoTestNGListener.class) 26 | // MockitoSettings with default values 27 | @MockitoSettings 28 | public class StrictStubsTest { 29 | 30 | @Mock 31 | List list; 32 | 33 | @Test 34 | public void detects_potential_stubbing_problem() { 35 | when(list.add("a")).thenReturn(true); 36 | 37 | Assertions.assertThatThrownBy(() -> StrictStubsCode.testStrictStubs(list, "b")) 38 | .isInstanceOf(PotentialStubbingProblem.class); 39 | } 40 | 41 | @Test public void detects_unused_stubs() { 42 | //when 43 | TestNGRunner.Result result = new TestNGRunner().run(HasUnusedStubs.class); 44 | 45 | //then 46 | assertThat(result.getFailure()).isInstanceOf(UnnecessaryStubbingException.class); 47 | } 48 | 49 | @Test 50 | public void detects_unused_stubs_in_setup() { 51 | //when 52 | TestNGRunner.Result result = new TestNGRunner().run(HasUnusedStubsInSetup.class); 53 | 54 | //then 55 | assertThat(result.getFailure()).isInstanceOf(UnnecessaryStubbingException.class); 56 | } 57 | 58 | @Test 59 | public void keeps_tests_dry() { 60 | //when 61 | when(list.add("a")).thenReturn(true); 62 | list.add("a"); 63 | 64 | //then used stubbing is implicitly verified 65 | verifyNoMoreInteractions(list); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /docs/release-notes.md: -------------------------------------------------------------------------------- 1 | *Release notes were automatically generated by [Shipkit](http://shipkit.org/)* 2 | 3 | #### 0.1.6 4 | - from version 0.1.6 see the [releases](https://github.com/mockito/mockito-testng/releases). 5 | 6 | #### 0.1.2 7 | - 2020-11-20 - [11 commits](https://github.com/mockito/mockito-testng/compare/v0.1.1...v0.1.2) by [Szczepan Faber](https://github.com/mockitoguy) (7), [Slawomir Jaranowski](https://github.com/slawekjaranowski) (3), [Matthew Ouyang](https://github.com/mouyang) (1) - published to [![Bintray](https://img.shields.io/badge/Bintray-0.1.2-green.svg)](https://bintray.com/mockito/maven/mockito-testng/0.1.2) 8 | - Update project dependencies [(#16)](https://github.com/mockito/mockito-testng/pull/16) 9 | - Add LICENSE file [(#13)](https://github.com/mockito/mockito-testng/pull/13) 10 | - Update / add information in README.md [(#12)](https://github.com/mockito/mockito-testng/pull/12) 11 | - change from oraclejdk8 to openjdk8 [(#9)](https://github.com/mockito/mockito-testng/pull/9) 12 | - Added information about release process [(#5)](https://github.com/mockito/mockito-testng/pull/5) 13 | - Whitespace change for PR [(#4)](https://github.com/mockito/mockito-testng/pull/4) 14 | 15 | #### 0.1.1 16 | - 2018-10-08 - [2 commits](https://github.com/mockito/mockito-testng/compare/v0.1.0...v0.1.1) by [Szczepan Faber](https://github.com/mockitoguy) - published to [![Bintray](https://img.shields.io/badge/Bintray-0.1.1-green.svg)](https://bintray.com/mockito/maven/mockito-testng/0.1.1) 17 | - No pull requests referenced in commit messages. 18 | 19 | #### 0.1.0 20 | - 2018-09-12 - [16 commits](https://github.com/mockito/mockito-testng/compare/v0.0.2...v0.1.0) by [Szczepan Faber](https://github.com/mockitoguy) - published to [![Bintray](https://img.shields.io/badge/Bintray-0.1.0-green.svg)](https://bintray.com/mockito/maven/mockito-testng/0.1.0) 21 | - TestNG integration uses strict stubbing feature by default [(#2)](https://github.com/mockito/mockito-testng/pull/2) 22 | - Make strict stubs the default setting for TestNGListener [(#1)](https://github.com/mockito/mockito-testng/issues/1) 23 | 24 | #### 0.0.2 25 | - 2018-08-02 - [3 commits](https://github.com/mockito/mockito-testng/compare/v0.0.1...v0.0.2) by [Szczepan Faber](https://github.com/mockitoguy) - published to [![Bintray](https://img.shields.io/badge/Bintray-0.0.2-green.svg)](https://bintray.com/mockito/maven/mockito-testng/0.0.2) 26 | - No pull requests referenced in commit messages. 27 | 28 | #### 0.0.1 29 | - 2018-08-01 - 3 commits by [Szczepan Faber](https://github.com/mockitoguy) - published to [![Bintray](https://img.shields.io/badge/Bintray-0.0.1-green.svg)](https://bintray.com/mockito/maven/mockito-testng/0.0.1) 30 | - No pull requests referenced in commit messages. 31 | 32 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # 2 | # CI build that assembles artifacts and runs tests. 3 | # If validation is successful this workflow releases from the main dev branch. 4 | # 5 | # - skipping CI: add [skip ci] to the commit message 6 | # - skipping release: add [skip release] to the commit message 7 | # 8 | name: CI 9 | 10 | on: 11 | push: 12 | branches: ['master'] 13 | tags: [v*] 14 | pull_request: 15 | branches: ['**'] 16 | 17 | jobs: 18 | 19 | # 20 | # SINGLE-JOB 21 | # 22 | verify: 23 | runs-on: ubuntu-latest 24 | if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')" 25 | 26 | steps: 27 | 28 | - name: 1. Check out code 29 | uses: actions/checkout@v6 # https://github.com/actions/checkout 30 | 31 | - name: 2. Set up Java 11 32 | uses: actions/setup-java@v5 # https://github.com/actions/setup-java 33 | with: 34 | java-version: 11 35 | distribution: 'zulu' 36 | 37 | - name: 3. Validate Gradle wrapper 38 | uses: gradle/wrapper-validation-action@v3.5.0 # https://github.com/gradle/wrapper-validation-action 39 | 40 | - name: 4. Build and check reproducibility of artifacts 41 | run: ./check_reproducibility.sh 42 | 43 | # 44 | # Main build job 45 | # 46 | build: 47 | needs: [verify] 48 | runs-on: ${{ matrix.os }} 49 | 50 | # Definition of the build matrix 51 | strategy: 52 | matrix: 53 | java: [11, 17] 54 | os: [ ubuntu-latest, windows-latest, macOS-latest ] 55 | 56 | steps: 57 | 58 | - name: 1. Check out code 59 | uses: actions/checkout@v6 # https://github.com/actions/checkout 60 | 61 | - name: 2. Set up Java ${{ matrix.java }} 62 | uses: actions/setup-java@v5 # https://github.com/actions/setup-java 63 | with: 64 | java-version: ${{ matrix.java }} 65 | distribution: 'temurin' 66 | 67 | - name: 3. Build on ${{ matrix.os }} with Java ${{ matrix.java }} 68 | run: ./gradlew build idea 69 | 70 | # 71 | # Release job, only for pushes to the main development branch 72 | # 73 | 74 | release: 75 | concurrency: release 76 | runs-on: ubuntu-latest 77 | needs: [verify, build] # build job must pass before we can release 78 | 79 | if: github.event_name == 'push' 80 | && startsWith(github.ref, 'refs/tags/v') 81 | && github.repository == 'mockito/mockito-testng' 82 | && !contains(toJSON(github.event.commits.*.message), '[skip release]') 83 | 84 | steps: 85 | 86 | - name: Check out code 87 | uses: actions/checkout@v6 # https://github.com/actions/checkout 88 | with: 89 | fetch-depth: '0' # https://github.com/shipkit/shipkit-changelog#fetch-depth-on-ci 90 | 91 | - name: Set up Java 11 92 | uses: actions/setup-java@v5 93 | with: 94 | java-version: 11 95 | distribution: 'zulu' 96 | 97 | - name: Build and publish to Sonatype/MavenCentral 98 | run: ./gradlew publishToSonatype closeAndReleaseStagingRepositories githubRelease 99 | env: 100 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 101 | NEXUS_TOKEN_USER: ${{secrets.NEXUS_TOKEN_USER}} 102 | NEXUS_TOKEN_PWD: ${{secrets.NEXUS_TOKEN_PWD}} 103 | PGP_KEY: ${{secrets.PGP_KEY}} 104 | PGP_PWD: ${{secrets.PGP_PWD}} 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mockito for TestNG 2 | 3 | Mockito utility classes for easy integration with TestNG 4 | 5 | [![CI](https://github.com/mockito/mockito-testng/workflows/CI/badge.svg)](https://github.com/mockito/mockito-testng/actions?query=workflow%3ACI) 6 | 7 | [![Maven Central](https://img.shields.io/maven-central/v/org.mockito/mockito-testng.svg)](https://search.maven.org/artifact/org.mockito/mockito-testng/) 8 | 9 | ## Installation 10 | 11 | ### Gradle 12 | ```Gradle 13 | dependencies { 14 | testCompile "org.mockito:mockito-testng:VERSION" 15 | } 16 | ``` 17 | 18 | ### Maven 19 | ```xml 20 | 21 | org.mockito 22 | mockito-testng 23 | VERSION 24 | test 25 | 26 | ``` 27 | 28 | For latest version, see the [releases](https://github.com/mockito/mockito-testng/releases). 29 | 30 | ## Usage 31 | 32 | Simply add `@Listeners` annotation on your test class 33 | 34 | ```java 35 | import org.mockito.InjectMocks; 36 | import org.mockito.Mock; 37 | import org.mockito.testng.MockitoTestNGListener; 38 | import org.testng.annotations.Listeners; 39 | import org.testng.annotations.Test; 40 | 41 | import java.util.Map; 42 | 43 | @Listeners(MockitoTestNGListener.class) 44 | public class MyTest { 45 | 46 | @Mock 47 | Map map; 48 | 49 | @InjectMocks 50 | SomeType someType; 51 | 52 | @Test 53 | void test() { 54 | // ... 55 | } 56 | } 57 | ``` 58 | 59 | `MockitoTestNGListener` will do job for you and initialize all fields annotated with mockito annotations. 60 | 61 | By default `MockitoSession` is started with `STRICT_STUBS`. 62 | You can change this behavior by adding `@MockitoSettings` to your test class. 63 | 64 | ```java 65 | import org.mockito.quality.Strictness; 66 | import org.mockito.testng.MockitoTestNGListener; 67 | import org.mockito.testng.MockitoSettings; 68 | import org.testng.annotations.Listeners; 69 | 70 | @Listeners(MockitoTestNGListener.class) 71 | @MockitoSettings(strictness = Strictness.WARN) 72 | public class MyTest { 73 | // ... 74 | } 75 | ``` 76 | 77 | ## Notices 78 | 79 | - `MockitoSession` is started before each `test method` or before method annotated with `@BeforeMethod`, 80 | another annotations `@BeforeXXX` aren't supported #40 81 | 82 | ## Developing 83 | 84 | - open in IDEA to develop or run ```./gradlew idea``` and then open in IDEA 85 | - ```./gradlew build``` - tests code and assembles artifacts 86 | - ```./gradlew publishToMavenLocal``` - publishes to local Maven repo, useful for local testing 87 | 88 | ## Releasing 89 | 90 | Every merged pull request is published to Maven Central. 91 | Actually, any change on master that happily builds on CI is published. 92 | The release automation uses Shipkit framework (http://shipkit.org). 93 | 94 | ## History 95 | 96 | The original TestNGListener was a part of the core Mockito repository. However, the jar was never released. Core Mockito team does not work with TestNG so it was hard for us to maintain TestNG integration. In Summer 2018 we moved the TestNG integration to a separate repository under "Mockito" organization. 97 | 98 | ## Help 99 | 100 | We are looking for maintainers of TestNG integration! Let us know if you want to join. Mockito core team has limited capacity and focuses on the core library. 101 | -------------------------------------------------------------------------------- /src/test/java/org/mockitousage/testng/utils/TestNGRunner.java: -------------------------------------------------------------------------------- 1 | package org.mockitousage.testng.utils; 2 | 3 | import org.testng.IConfigurationListener; 4 | import org.testng.ITestContext; 5 | import org.testng.ITestListener; 6 | import org.testng.ITestResult; 7 | import org.testng.TestNG; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.ListIterator; 12 | 13 | public class TestNGRunner { 14 | 15 | public Result run(Class ... testClasses) { 16 | TestNG testNG = new TestNG(); 17 | testNG.setVerbose(0); 18 | testNG.setUseDefaultListeners(false); 19 | 20 | FailureRecordingListener failureRecorder = new FailureRecordingListener(); 21 | testNG.addListener(failureRecorder); 22 | 23 | testNG.setTestClasses(testClasses); 24 | 25 | // run test in separate thread in order to avoid conflict MockitoSession from parent test 26 | Thread testThread = new Thread(testNG::run); 27 | testThread.start(); 28 | try { 29 | testThread.join(); 30 | } catch (InterruptedException e) { 31 | Thread.currentThread().interrupt(); 32 | } 33 | 34 | return new Result(testNG, failureRecorder); 35 | } 36 | 37 | public static class Result { 38 | private final TestNG testNG; 39 | private final FailureRecordingListener failureRecorder; 40 | 41 | public Result(TestNG testNG, FailureRecordingListener failureRecorder) { 42 | this.testNG = testNG; 43 | this.failureRecorder = failureRecorder; 44 | } 45 | 46 | public Throwable getFailure() { 47 | Throwable failure = failureRecorder.lastThrowable(); 48 | if (failure != null && !testNG.hasFailure()) { 49 | throw new AssertionError("Failure was recorded but TestNG does not indicate a failure."); 50 | } 51 | return failure; 52 | } 53 | } 54 | 55 | /** 56 | * Not thread-safe listener that record only failures, either on the test or on a configuration method. 57 | */ 58 | public static class FailureRecordingListener implements ITestListener, IConfigurationListener { 59 | 60 | public List failedTestResults = new ArrayList<>(); 61 | 62 | public void onTestFailure(ITestResult result) { 63 | failedTestResults.add(result); 64 | } 65 | 66 | public void onConfigurationFailure(ITestResult result) { 67 | failedTestResults.add(result); 68 | } 69 | 70 | public Throwable lastThrowable() { 71 | ListIterator iterator = failedTestResults.listIterator(failedTestResults.size()); 72 | return iterator.hasPrevious() ? iterator.previous().getThrowable() : null; 73 | } 74 | 75 | public void clear() { 76 | failedTestResults.clear(); 77 | } 78 | 79 | // don't care bellow 80 | 81 | 82 | public void onConfigurationSuccess(ITestResult itr) { } 83 | public void onConfigurationSkip(ITestResult itr) { } 84 | public void onTestStart(ITestResult result) { } 85 | public void onTestSuccess(ITestResult result) { } 86 | public void onTestSkipped(ITestResult result) { } 87 | public void onTestFailedButWithinSuccessPercentage(ITestResult result) { } 88 | public void onStart(ITestContext context) { } 89 | public void onFinish(ITestContext context) { } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /gradle/java-publication.gradle: -------------------------------------------------------------------------------- 1 | //Sources/javadoc artifacts required by Maven module publications 2 | def licenseSpec = copySpec { 3 | from project.rootDir 4 | include "LICENSE" 5 | } 6 | 7 | task sourcesJar(type: Jar, dependsOn: classes) { 8 | archiveClassifier.set('sources') 9 | from sourceSets.main.allSource 10 | with licenseSpec 11 | } 12 | 13 | task javadocJar(type: Jar, dependsOn: javadoc) { 14 | archiveClassifier.set('javadoc') 15 | from tasks.javadoc 16 | with licenseSpec 17 | } 18 | 19 | jar { 20 | with licenseSpec 21 | } 22 | 23 | artifacts { 24 | archives sourcesJar 25 | archives javadocJar 26 | } 27 | 28 | //Gradle Maven publishing plugin configuration (https://docs.gradle.org/current/userguide/publishing_maven.html) 29 | apply plugin: "maven-publish" 30 | publishing { 31 | publications { 32 | javaLibrary(MavenPublication) { //name of the publication 33 | from components.java 34 | artifact sourcesJar 35 | artifact javadocJar 36 | 37 | artifactId = project.archivesBaseName 38 | 39 | pom { 40 | name = artifactId 41 | description = project.description 42 | 43 | url = "https://github.com/mockito/mockito-testng" 44 | licenses { 45 | license { 46 | name = 'The MIT License' 47 | url = 'https://github.com/mockito/mockito-testng/blob/master/LICENSE' 48 | distribution = 'repo' 49 | } 50 | } 51 | developers { 52 | ['mockitoguy:Szczepan Faber', 53 | 'mouyang:Matthew Ouyang', 54 | 'skabashnyuk:Sergii Kabashniuk', 55 | 'slawekjaranowski:Slawomir Jaranowski'].each { devData -> 56 | developer { 57 | def devInfo = devData.split(':') 58 | id = devInfo[0] 59 | name = devInfo[1] 60 | url = 'https://github.com/' + devInfo[0] 61 | roles = ["Core developer"] 62 | } 63 | } 64 | } 65 | scm { 66 | url = 'https://github.com/mockito/mockito-testng.git' 67 | } 68 | issueManagement { 69 | url = 'https://github.com/mockito/mockito-testng/issues' 70 | system = 'GitHub issues' 71 | } 72 | ciManagement { 73 | url = 'https://github.com/mockito/mockito-testng/actions' 74 | system = 'GH Actions' 75 | } 76 | } 77 | } 78 | } 79 | 80 | //useful for testing - running "publish" will create artifacts/pom in a local dir 81 | repositories { maven { url = "$buildDir/repo" } } 82 | } 83 | 84 | //fleshes out problems with Maven pom generation when building 85 | tasks.build.dependsOn("publishJavaLibraryPublicationToMavenLocal") 86 | 87 | apply plugin: 'signing' //https://docs.gradle.org/current/userguide/signing_plugin.html 88 | signing { 89 | if (System.getenv('PGP_KEY')) { 90 | useInMemoryPgpKeys(System.getenv('PGP_KEY'), System.getenv('PGP_PWD')) 91 | sign publishing.publications.javaLibrary 92 | } 93 | } 94 | 95 | apply plugin: 'io.github.gradle-nexus.publish-plugin' 96 | nexusPublishing { 97 | repositories { 98 | if (System.getenv('NEXUS_TOKEN_PWD')) { 99 | sonatype { 100 | nexusUrl = uri('https://ossrh-staging-api.central.sonatype.com/service/local/') 101 | snapshotRepositoryUrl = uri('https://central.sonatype.com/repository/maven-snapshots/') 102 | 103 | username = System.getenv('NEXUS_TOKEN_USER') 104 | password = System.getenv('NEXUS_TOKEN_PWD') 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /src/main/java/org/mockito/testng/MockitoTestNGListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Mockito contributors 3 | * This program is made available under the terms of the MIT License. 4 | */ 5 | package org.mockito.testng; 6 | 7 | import java.lang.annotation.Annotation; 8 | import java.lang.reflect.Field; 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.Optional; 15 | import java.util.stream.Stream; 16 | 17 | import org.mockito.InjectMocks; 18 | import org.mockito.Mockito; 19 | import org.mockito.MockitoSession; 20 | import org.mockito.internal.util.reflection.InstanceField; 21 | import org.mockito.quality.Strictness; 22 | import org.testng.IInvokedMethod; 23 | import org.testng.IInvokedMethodListener; 24 | import org.testng.ITestResult; 25 | import org.testng.annotations.Listeners; 26 | 27 | /** 28 | *

Mockito TestNG Listener, this listener initializes mocks and handles strict stubbing, it is similar to JUnit 29 | * MockitoJUnitRunner, MockitoRule, MockitoExtension and adds 30 | * the following behavior to your test:

31 | * 32 | *
    33 | *
  • 34 | * Before any test method or a configuration method @BeforeMethod 35 | * MockitoSession is started by: 36 | * 37 | *
    
     38 |  *         Mockito.mockitoSession()
     39 |  *          .initMocks(testInstance)
     40 |  *          .strictness(Strictness.STRICT_STUBS)
     41 |  *          .startMocking()
     42 |  *         
    43 | * See javadoc {@link MockitoSession} 44 | *
  • 45 | *
  • 46 | * After each test method {@link MockitoSession#finishMocking()} is called. 47 | *
  • 48 | *
49 | * 50 | *

Example usage:

51 | *

 52 |  * @Listeners(MockitoTestNGListener.class)
 53 |  * public class ExampleTest {
 54 |  *
 55 |  *     @Mock
 56 |  *     private List list;
 57 |  *
 58 |  *     @Test
 59 |  *     public void shouldDoSomething() {
 60 |  *         list.add(100);
 61 |  *     }
 62 |  * }
 63 |  * 
64 | * 65 | *

66 | * By default {@link MockitoSession} is started with {@link Strictness#STRICT_STUBS}. 67 | * You can change this behavior by adding {@link MockitoSettings} to your test class. 68 | *

69 | * 70 | *

 71 |  * @Listeners(MockitoTestNGListener.class)
 72 |  * @MockitoSettings(strictness = Strictness.WARN)
 73 |  * public class ExampleTest {
 74 |  *  ...
 75 |  * }
 76 |  * 
77 | * 78 | *

79 | * MockitoTestNGListener not working with parallel tests, 80 | * more information https://github.com/mockito/mockito-testng/issues/20 81 | *

82 | */ 83 | public class MockitoTestNGListener implements IInvokedMethodListener { 84 | 85 | private final Map sessions = new HashMap<>(); 86 | private final Map> injectMocksFieldsValues = new HashMap<>(); 87 | 88 | @Override 89 | public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { 90 | if (shouldBeRunBeforeInvocation(method, testResult)) { 91 | 92 | // save value of all InjectMocks fields 93 | // in order to restore state before next tests 94 | // https://github.com/mockito/mockito-testng/issues/28 95 | injectMocksFieldsValues.computeIfAbsent(testResult.getInstance(), testInstance -> 96 | allDeclaredFieldsOf(testInstance) 97 | .stream() 98 | .filter(field -> field.isAnnotatedBy(InjectMocks.class)) 99 | .collect(HashMap::new, (m, v) -> m.put(v, v.read()), HashMap::putAll)); 100 | 101 | sessions.computeIfAbsent(testResult.getInstance(), testInstance -> { 102 | 103 | Strictness strictness = findAnnotation(testResult, MockitoSettings.class) 104 | .map(MockitoSettings::strictness).orElse(Strictness.STRICT_STUBS); 105 | 106 | // start MockitoSession 107 | return Mockito.mockitoSession() 108 | .initMocks(testInstance) 109 | .strictness(strictness) 110 | .startMocking(); 111 | } 112 | ); 113 | } 114 | } 115 | 116 | @Override 117 | public void afterInvocation(IInvokedMethod method, ITestResult testResult) { 118 | if (shouldBeRunAfterInvocation(method, testResult)) { 119 | try { 120 | Optional.ofNullable(sessions.remove(testResult.getInstance())) 121 | .ifPresent(mockitoSession -> mockitoSession.finishMocking(testResult.getThrowable())); 122 | } finally { 123 | Optional.ofNullable(injectMocksFieldsValues.remove(testResult.getInstance())) 124 | .ifPresent(fieldsValues -> fieldsValues.forEach(InstanceField::set)); 125 | } 126 | } 127 | } 128 | 129 | private boolean shouldBeRunBeforeInvocation(IInvokedMethod method, ITestResult testResult) { 130 | return (method.isTestMethod() || isBeforeMethod(method)) && hasMockitoTestNGListener(testResult); 131 | } 132 | 133 | private boolean isBeforeMethod(IInvokedMethod method) { 134 | return method.getTestMethod().isBeforeMethodConfiguration(); 135 | } 136 | 137 | private boolean shouldBeRunAfterInvocation(IInvokedMethod method, ITestResult testResult) { 138 | return method.isTestMethod() && hasMockitoTestNGListener(testResult); 139 | } 140 | 141 | protected boolean hasMockitoTestNGListener(ITestResult testResult) { 142 | 143 | return findAnnotation(testResult, Listeners.class) 144 | .map(Listeners::value) 145 | .map(Arrays::stream) 146 | .orElseGet(Stream::empty) 147 | .anyMatch(listener -> listener == MockitoTestNGListener.class); 148 | } 149 | 150 | Optional findAnnotation(ITestResult testResult, Class annotationClass) { 151 | 152 | for (Class clazz = testResult.getTestClass().getRealClass(); 153 | clazz != Object.class; clazz = clazz.getSuperclass()) { 154 | Optional annotation = Optional.ofNullable(clazz.getAnnotation(annotationClass)); 155 | if (annotation.isPresent()) { 156 | return annotation; 157 | } 158 | } 159 | 160 | return Optional.empty(); 161 | } 162 | 163 | private static List allDeclaredFieldsOf(Object testInstance) { 164 | List result = new ArrayList<>(); 165 | for (Class clazz = testInstance.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) { 166 | for (Field field : clazz.getDeclaredFields()) { 167 | result.add(new InstanceField(field, testInstance)); 168 | } 169 | } 170 | return result; 171 | } 172 | } 173 | --------------------------------------------------------------------------------