mae
mae

Reputation: 117

Can i mock file.mkdirs() which is inside of a method

Here is my legacy code below. I don't want to create an actual folder. Instead I want to create a temp folder, which has to be deleted after test execution is over.

Public class MainClass() {
  public void m1() {
        m2();
  }

  private void m2() {
    File f=new File();
    f.mkrdirs()
  }
}

Here is my TestClass

public class TestClass{
       @Rule
       public TemporaryFolder folder= new TemporaryFolder();

       public void testM1(){
            File fileSpy = mock(File.class);
            Mockito.doNothing().when(fileSpy.mkdir());

       }
}

but not working.Any clues?

Upvotes: 1

Views: 1400

Answers (1)

GhostCat
GhostCat

Reputation: 140427

Your problem starts here:

File f=new File();

Your production code calls new for the file class. In your test code, you do:

File fileSpy = mock(File.class);

And how is that spy related to your f instance? Answer: not at all.

Declaring a spy in your test doesn't magically make your production code use it! So you have to make sure that when your production code uses that f object ... f should be your fileSpy

Now you have these options:

  • see if you can change your production code, so that you can somehow pass in a file instance. Either by making it an argument, that you really can pass something to, or by turning f into a field of your class, to then use Mockito's @InjectMock annotation
  • if you are stuck with your production code, Mockito won't do. Then you need PowerMock(ito) or JMockit.

Typically, I advise people to stick with plain Mockito, and avoid mocking new() (even more so mocking static calls) via PowerMock(ito) like the plague.

But testing legacy code is the one situation where you have to choose between "not testing at all" or "testing with PowerMock(ito)". So, if you can't change your production code, then your only choice would be to mock that call to new(). See here for how to do that.

Upvotes: 4

Related Questions