What is the correct way to mock a final class with Mockito?

What is the correct way to mock a final class with Mockito?

I have a final class like this:

public final class RainOnTrees {
   public void startRain() {
        // some code here
   }
}

I am using this class inside another class:

public class Seasons {
   RainOnTrees rain = new RainOnTrees();

   public void findSeasonAndRain() {
        rain.startRain();
    }
}

In my JUnit test class for Seasons.java, I want to mock the RainOnTrees class. How can I do this using Mockito?

Use Mockito Inline Mocking (for Mockito 3.4.0+):

Add the mockito-inline dependency. Mock the final class directly in the test:

RainOnTrees rainMock = mock(RainOnTrees.class);
Seasons seasons = new Seasons();
seasons.rain = rainMock;
seasons.findSeasonAndRain();
verify(rainMock).startRain();

Add PowerMock dependency and use @PrepareForTest to mock the final class:

@RunWith(PowerMockRunner.class)
@PrepareForTest(RainOnTrees.class)
public class SeasonsTest {
    @Test
    public void testFindSeasonAndRain() {
        RainOnTrees rainMock = mock(RainOnTrees.class);
        PowerMockito.whenNew(RainOnTrees.class).withNoArguments().thenReturn(rainMock);
        Seasons seasons = new Seasons();
        seasons.findSeasonAndRain();
        verify(rainMock).startRain();
    }
}

Inject RainOnTrees via the constructor in the Seasons class:

public class Seasons {
    RainOnTrees rain;
    public Seasons(RainOnTrees rain) { this.rain = rain; }
    public void findSeasonAndRain() { rain.startRain(); }
}

In the test:

RainOnTrees rainMock = mock(RainOnTrees.class);
Seasons seasons = new Seasons(rainMock);
seasons.findSeasonAndRain();
verify(rainMock).startRain();