htafoya
htafoya

Reputation: 19283

Mockito lenient() when to use

As I understand, lenient silences the exceptions thrown by StrictStubbing. Based on this, lenient shouldn't be used, maybe only temporary while doing TDD, because strict stubbing exceptions would generally mean that your code is either wrong, test is badly designed or you are adding unnecessary lines.

Is there a practical scenario where lenient is actually needed or useful for the test?

Upvotes: 28

Views: 107606

Answers (6)

serv-inc
serv-inc

Reputation: 38267

Similar case to what HughG wrote:

  1. a bug was reported
  2. a test was written to reproduce the bug, with a mock for this branch of execution
  3. the code was fixed/rewritten/extended
  4. the mock was no longer used in the test, so it was flagged by mockito
  5. the rewrite was buggy. This would have been spotted with the mock in-place, but a different branch was chosen without mock.

fix: lenient().mock(... for this single mock in this single test case, to guard against the test not failing even though it should.

Upvotes: 0

Samurai Soul
Samurai Soul

Reputation: 245

lenient() can also be useful if you're writing a parameterized test. Parameterized tests can reduce redundant code a lot more than strict stubbing can. So if you're using a parameterized test (to test all of your exceptional conditions, for example), you may want lenient() stubbing if some invocations need a stub while others don't. Make your stubs as specific as possible first though.

Upvotes: 6

Ryan Peterson
Ryan Peterson

Reputation: 739

A good example of when to use lenient is in a @BeforeEach block.

If you use the stub in almost all the test cases, it makes sense to create the stub in a before each. If you have any tests that don't use the stub, you'll need to use lenient to prevent the strict stubbing from throwing an error. This is the example used in the mockito docs:

  @Before public void before() {
      when(foo.foo()).thenReturn("ok");

      // it is better to configure the stubbing to be lenient:
      // lenient().when(foo.foo()).thenReturn("ok");

      // or the entire mock to be lenient:
      // foo = mock(Foo.class, withSettings().lenient());
  }

  @Test public void test1() {
      foo.foo();
  }

  @Test public void test2() {
      foo.foo();
  }

  @Test public void test3() {
      bar.bar();
  } 

Upvotes: 28

pinaci
pinaci

Reputation: 353

Strict Stubbing is introduced to detect unnecessary stubs and write a much cleaner test. If you are getting exceptions, focus should be on improving test cases and not to by-pass strict stubbing check.

Upvotes: 7

HughG
HughG

Reputation: 1118

I just came across an unusual valid use for this. We made a code change which disabled a feature by default (prior to taking it out altogether in a future release). We needed a test that the disabling actually worked, so we needed to mock some flag as false. However, we also needed to mock a few other values becaues, if the bit of code to disable the feature (which tested that flag) got broken somehow, the default settings for the feature would cause it to do nothing anyway, so we wouldn't be able to observe failure of the flag.

To summarise: in the success case, we would get UnnecessaryStubbingException with the mocking but, without it, the failure case wouldn't actually fail. Hence we marked those specific mockings as lenient.

Upvotes: 6

amseager
amseager

Reputation: 6391

For example, it's very useful while migrating from Mockito 1 to Mockito 2 (the latter introduced strict stubbing), if you need to do it in a short period of time.

Upvotes: 10

Related Questions