Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Mock System.getProperty using Mockito

I have added mock-maker-inline text in org.mockito.plugins.MockMaker file and placed it in test/resources/mockito-extensions

In my test case I am using:

System system = mock(System.class);
when(system.getProperty("flag")).thenReturn("true");`

But I am getting the following exception:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

Appreciate any suggestions

like image 494
Raghu Avatar asked Jan 30 '18 20:01

Raghu


People also ask

Can we mock system class?

System class is declared as final and cannot be mocked by libraries such as PowerMock. Several answers posted here are incorrect. If you are using Apache System Utils you can use getEnvironmentVariable method instead of calling System.

How do I set system properties in Junit?

If your test relies on system properties you could set them and unset them in 'before' and 'after' lifecycle methods. In Junit5, setting system properties for all tests in a test case might look like this: @BeforeAll public static void setSystemProperties() { // set the system properties // ... }

How do I use stubs in Junit?

A stub is a fake class that comes with preprogrammed return values. It's injected into the class under test to give you absolute control over what's being tested as input. A typical stub is a database connection that allows you to mimic any scenario without having a real database.


2 Answers

Your could also use real methods, preparing and removing the configuration before and after each test:

@Before
public void setUp() {
    System.setProperty("flag", "true");
}

@After
public void tearDown() {
    System.clearProperty("flag");
}
like image 73
Jose Tepedino Avatar answered Oct 18 '22 19:10

Jose Tepedino


The System.getProperty() method is static, in order to mock this you'll need to use PowerMock.

Here's an example:

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

import static org.junit.Assert.assertEquals;

@RunWith(PowerMockRunner.class)
@PrepareForTest(System.class)
public class ATest {

    @Test
    public void canMockSystemProperties() {
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getProperty("flag")).thenReturn("true");

        assertEquals("true", System.getProperty("flag"));
    }
}

This uses:

  • junit:junit:4.12
  • org.mockito:mocktio-core:2.7.19
  • org.powermock:powermock-api-mockito2:1.7.0
  • org.powermock:powermock-module-junit4:1.7.0

Note: @davidxxx's suggestion of avoiding the need to mock this by hiding all System access behind a facade is very sensible. Another way of avoiding the need to mock System is to actually set the desired value as a system property when running your test, System Rules offers a neat way of setting up and tearing down System property expectations in the context of Junit tests.

like image 5
glytching Avatar answered Oct 18 '22 19:10

glytching