问题
I am currently writing tests to a legacy code which uses a function System.getenv("some_environment_variable")
I get a problem when I try to mock these variables by using mockito and powermock (used under testng framework)
What I did so far was
@BeforeClass
public void setup() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getenv("hello")).thenReturn("world");
}
@Test
public void test() {
assertEquals(System.getenv("hello"), "world");
}
But when I tried to run the code above i get the following error:
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:
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.
inside when() you don't call method on mock but on some other object.
So Iv'e read and saw that this error raised when trying to mock a method with mocking the class itself, but this is not the case here.
回答1:
After toying around with this for quite sometime, here's how I managed to do it.
In a nutshell, in order to get powermockito and TestNG to work with each other you have to do the following (quoting from the blog post whose link is shared below so that the answer is complete and will be useful even if the blog is not available at a later point in time)
Configure TestNG to use the PowerMock object factory : You can do this either via the attribute
object-factory
in your<suite>
tag of your suite xml or via an@org.testng.annotations.ObjectFactory
annotated method which returns the powermock's implementation of TestNG interfaceorg.testng.IObjectFactory
viz.,org.powermock.modules.testng.PowerMockObjectFactory
(or) by extendingorg.powermock.modules.testng.PowerMockTestCase
Use
@PrepareForTest
to prepare your static class for being mocked by PowerMockito
Please refer to this blog for more details.
Here's a working sample:
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
@PrepareForTest(System.class)
public class SampleTestClass {
@BeforeClass
public void setup() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getenv("hello")).thenReturn("world");
}
@Test
public void test() {
assertEquals(System.getenv("hello"), "world");
}
@ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
}
I used the below dependencies for creating this sample
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-testng</artifactId>
<version>1.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.7.0</version>
<scope>test</scope>
</dependency>
回答2:
There is another JUnit library which may help you: system-rules, which will allow you to -- among other things -- set and restore environment variables. It is used in conjunction with JUnit @Rule
s
来源:https://stackoverflow.com/questions/45285416/mocking-system-class-method-using-testng-mockito-and-powermock