我能够从Junit模拟System.getenv值,但是当我执行测试用例时 - 在我的服务类System.getevn中,值为null。不知道我在这里做错了什么。请找我的测试服务类和junit类。
有些人可以帮我修复这个问题 - 为什么价值没有在我的实际服务类中设置?
TestService.java
public class TestService {
public TestService() throws Exception {
loadTestMethod();
}
private void loadTestMethod() {
System.out.println("Environment vairlable : " + System.getenv("my_key_name"));
System.setProperty("app.key", System.getenv("my_key_name"));
}
}
TestServiceTest.java
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(value = { System.class })
@PowerMockIgnore("javax.management.*")
public class TestServiceTest {
@Mock
TestService testService;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getenv("my_key_name")).thenReturn("Testing");
System.out.println("Junit Environment vairlable : " + System.getenv("my_key_name"));
testService = new TestService();
}
@Test
public void myServiceTest() {
}
}
答案 0 :(得分:1)
Just because PowerMockito allows us to mock static does not mean that we should.
Your classes are dependent on static implementation concerns that make unit testing in isolation, in most cases, difficult.
Consider following the Explicit Dependency Principle
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
Create an abstraction of the desired functionality
public interface SystemWrapper {
//The "standard" output stream
PrintStream out;
//Gets the value of the specified environment variable
string getenv(string name);
//Sets the system property indicated by the specified key.
string setProperty(String key, String value);
}
The implementation will encapsulate the actual calls to the static system class
public class SystemWrapperImplementation implements SystemWrapper {
//The "standard" output stream
public final PrintStream out = System.out;
//Gets the value of the specified environment variable
public string getenv(string name) {
return System.getenv(name);
}
//Sets the system property indicated by the specified key.
public string setProperty(String key, String value) {
return System.setProperty(key, value);
}
}
Your dependent class will then need to be refactored to include the abstraction
public class TestService {
private SystemWrapper system;
public TestService(SystemWrapper system) throws Exception {
this.system = system;
string key = "app.key";
string name = "my_key_name";
loadTestMethod(key, name);
}
private void loadTestMethod(string key, string name) {
string environmentVariable = system.getenv(name);
system.out.println("Environment variable : " + environmentVariable);
system.setProperty(key, environmentVariable);
}
}
Now for testing you can mock the necessary dependencies as needed without any adverse effects. The implementation will then be used in production when invoking actual code.
Finally I would suggest not having your constructors throwing exceptions. Constructors should mainly be used for assignments of variables.