Skip to content

Commit

Permalink
Fixes #3077 : Report unused stubbing exceptions when test filter is n…
Browse files Browse the repository at this point in the history
…o-op
  • Loading branch information
C0urante committed Aug 4, 2023
1 parent f5ad9e9 commit c989b91
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 5 deletions.
44 changes: 39 additions & 5 deletions src/main/java/org/mockito/internal/runners/StrictRunner.java
Expand Up @@ -16,7 +16,7 @@ public class StrictRunner implements InternalRunner {

private final Class<?> testClass;
private final InternalRunner runner;
private boolean filterRequested;
private volatile boolean testsSkipped;

/**
* @param runner - the runner to wrap around
Expand All @@ -25,6 +25,7 @@ public class StrictRunner implements InternalRunner {
public StrictRunner(InternalRunner runner, Class<?> testClass) {
this.runner = runner;
this.testClass = testClass;
this.testsSkipped = false;
}

@Override
Expand All @@ -43,9 +44,9 @@ public void run(RunNotifier notifier) {
Mockito.framework().removeListener(reporter);
}

if (!filterRequested && listener.isSuccessful()) {
if (!testsSkipped && listener.isSuccessful()) {
// only report when:
// 1. if all tests from given test have ran (filter requested is false)
// 1. if all tests from given test have ran (tests skipped is false)
// Otherwise we would report unnecessary stubs even if the user runs just single test
// from the class
// 2. tests are successful (we don't want to add an extra failure on top of any existing
Expand All @@ -61,7 +62,40 @@ public Description getDescription() {

@Override
public void filter(Filter filter) throws NoTestsRemainException {
filterRequested = true;
runner.filter(filter);
Filter recordingFilter = new RecordingFilter(filter);
runner.filter(recordingFilter);
}

private class RecordingFilter extends Filter {

private final Filter delegate;

public RecordingFilter(Filter delegate) {
this.delegate = delegate;
}

@Override
public void apply(Object child) throws NoTestsRemainException {
delegate.apply(child);
}

@Override
public Filter intersect(Filter second) {
return delegate.intersect(second);
}

@Override
public boolean shouldRun(Description description) {
boolean result = delegate.shouldRun(description);
if (!result) {
testsSkipped = true;
}
return result;
}

@Override
public String describe() {
return delegate.describe();
}
}
}
43 changes: 43 additions & 0 deletions src/test/java/org/mockitousage/junitrunner/StrictRunnerTest.java
Expand Up @@ -11,9 +11,12 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.RunWith;
import org.junit.runner.manipulation.Filter;
import org.mockito.Mock;
import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
import org.mockito.junit.MockitoJUnit;
Expand Down Expand Up @@ -84,6 +87,33 @@ public void runner_in_multi_threaded_tests() {
JUnitResultAssert.assertThat(result).isSuccessful();
}

@Test
public void does_not_report_unused_stubs_when_test_is_filtered() {
// This class has two test methods; run only the test method that does not use the stubbing set up in before
Request request = Request.method(StubbingInBeforeUsed.class, "dummy");

// when
Result result = runner.run(request);

// then
JUnitResultAssert.assertThat(result).isSuccessful();
}

@Test
public void fails_when_stubs_were_not_used_with_noop_filter() {
Class[] tests = {
StubbingInConstructorUnused.class,
StubbingInBeforeUnused.class,
StubbingInTestUnused.class
};

// when
Result result = runner.run(Request.classes(tests).filterWith(new NoOpFilter()));

// then
JUnitResultAssert.assertThat(result).fails(3, UnnecessaryStubbingException.class);
}

@RunWith(MockitoJUnitRunner.class)
public static class StubbingInConstructorUsed extends StubbingInConstructorUnused {
@Test
Expand Down Expand Up @@ -201,4 +231,17 @@ public void run() {
t.join();
}
}

private static class NoOpFilter extends Filter {

@Override
public boolean shouldRun(Description description) {
return true;
}

@Override
public String describe() {
return "No-op filter";
}
}
}

0 comments on commit c989b91

Please sign in to comment.