3

I am writing a test using Junit + Mockito + Powermock.

I have a class like following which I want to test:

public class MyUtils {
    public static Object method1() {} //I want to mock this only
    public static void method2() {}   //I want to keep this as is during my test.
    public static void method3() {}   //I want to keep this as is during my test.
}

I want to mock only method1 but not method2 or method3.

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyUtils.class)
public class MyTest {

    @Before
    public void setUpBeforeClass() throws Exception {
        PowerMockito.mockStatic(MyUtils.class);
    }

    @Test
    public void test1() throws Exception {
        when(MyUtils.method1()).thenReturn(something);

        MyUtils.method3(); //method3 is getting mocked with an empty implementation by PowerMockito
    }

    ...
}

Can I have some methods mocked and some not be mocked i.e. they keep their original implementation during the test? Is this possible with Mockito + Powermock?

My test may not look very elegant but I have simplified my usecase before posting here.

Thank you.

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
user674669
  • 10,681
  • 15
  • 72
  • 105
  • Possible duplicate of [Mock a single static method using PowerMock and TestNG](https://stackoverflow.com/questions/20398120/mock-a-single-static-method-using-powermock-and-testng) – Turing85 Oct 31 '17 at 23:22
  • With new version of Mockito we are able to mock static methods also. Do any one know how to solve this only using JUnit 5 + Mockito inline 3.7.7? – Prakash Boda Feb 12 '21 at 15:03

2 Answers2

3

Yes it is possible to mock static methods using Powermock and JUnit as below:

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;    
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest(IDGenerator.class)
public class UserDAOTest {
@Test
public void createShouldReturnAUserId() {

    UserDAO dao = new UserDAO();

    mockStatic(IDGenerator.class);
    when(IDGenerator.generateID()).thenReturn(1);
    int result = dao.create(new User());
    assertEquals(1, result);
    verifyStatic();
}

}


public final class IDGenerator {

static int i;

public static final int generateID() {
    return i++;
}

}


public class UserDAO {

public int create(User user){
    int id = IDGenerator.generateID();
    //Save the user object to the db
    return id;

}

}



public class User {
private int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

}

Hope it helps!

Samir
  • 655
  • 5
  • 14
2

If you have way more methods that you want to keep with real implementation than ones that need to be mocked (especially when its only one in your case) then I would go for spy instead of mock:

import static org.powermock.api.mockito.PowerMockito.spy;

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyUtils.class)
public class MyTest {

    @Before
    public void setUpBeforeClass() throws Exception {
        spy(MyUtils.class);
    }

    @Test
    public void test1() throws Exception {
        doReturn(something).when(MyUtils.class, "method1");

        MyUtils.method3(); // this will be a real call
    }

    ...
}

Now all the methods except method1 will be called with real implementation.

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
  • Keep in mind you cannot use the standard doX().when(mock).method when the mock is a class and method is static. Please use the version of the setup as above. – Maciej Kowalski Nov 01 '17 at 07:59