在已经花了很多时间在这个测试并不能对我这样推理出来的,我没有别的选择,而不是找你帮忙:)JMockit异常块上的NullPointerException?
使用JMockit测试一些我自己的JDBC“包装”的上课,我走到了死胡同。
这是类IM测试:
public class JdbcConnectionProperties {
private Properties properties = new Properties();
private String username;
private String password;
private String connectionString;
public JdbcConnectionProperties(String propertiesFilePath) {
loadProperties(propertiesFilePath);
}
public void setProperties() {
username = properties.getProperty("user");
password = properties.getProperty("password");
String connectionType = properties.getProperty("connection_type");
String serverAddress = properties.getProperty("server_address");
String port = properties.getProperty("port");
String sid = properties.getProperty("sid");
//Create a connection string
connectionString = "jdbc:oracle:" + connectionType + ":@" + serverAddress + ":" + port + ":" + sid;
}
private void loadProperties(String propertiesFilePath) {
String filePath = Thread.currentThread().getContextClassLoader().getResource(propertiesFilePath).getFile();
//Load properties from classpath
try {
properties.load(new FileInputStream(filePath));
} catch (IOException e) {
e.printStackTrace();
}
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getConnectionString() {
return connectionString;
}
public Properties getProperties() {
return properties;
}
}
这是测试:
public class JdbcConnectionPropertiesTest {
@Test
public void testSetProperties(
// @Mocked final Properties properties
) throws Exception {
//Mock loadFilePath method so i dont end up mocking a ton of classes
new MockUp<JdbcConnectionProperties>() {
@Mock
void loadProperties(String propertiesFilePath) {
//Doing nothing, simple "stub" method
}
};
JdbcConnectionProperties jdbcConnectionProperties = new JdbcConnectionProperties("bla");
// Deencapsulation.setField(jdbcConnectionProperties, "properties", properties);
// Mockit.stubOutClass(JdbcConnectionProperties.class, "loadProperties");
final String username = "username";
final String password = "password";
final String connectionType = "thin";
final String serverAddress = "localhost";
final String port = "1521";
final String sid = "orcl";
String connectionString = "jdbc:oracle:" + connectionType + ":@" + serverAddress + ":" + port + ":" + sid;
new Expectations() {
@Mocked
Properties properties;
{
properties.get("user");
result = username;
properties.get("password");
result = password;
properties.get("connection_type");
result = connectionType;
properties.get("server_address");
result = serverAddress;
properties.get("port");
result = port;
properties.get("sid");
result = sid;
}
};
jdbcConnectionProperties.setProperties();
Assert.assertEquals("Incorrect user", username, jdbcConnectionProperties.getUsername());
Assert.assertEquals("Incorrect password", password, jdbcConnectionProperties.getPassword());
Assert.assertEquals("Incorrect connection string", connectionString, jdbcConnectionProperties.getConnectionString());
}
}
有两点要注意。我尝试用Deencapsulation将嘲讽的属性隐藏到对象中(我让他们在代码中注释)。
我试着用@Mocked注释来嘲笑它。
我试着用stubOutClass存根。
这不是我正在写的第一个测试,但是我相对比较新的JMockit。 我之前写的测试从来没有让我像这样的头痛。我想我用JMockit写了大约20-30个测试,从来没有像这样的问题。
错误的是(在所有提到的情况):
java.lang.NullPointerException
at java.util.Hashtable.get(Hashtable.java:335)
at jdbc.JdbcConnectionPropertiesTest$2.<init>(JdbcConnectionPropertiesTest.java:49)
at jdbc.JdbcConnectionPropertiesTest.testSetProperties(JdbcConnectionPropertiesTest.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:71)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:199)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
类是非常简单的。测试应该非常简单。但不知何故测试会在Expectations块上崩溃(在第一个属性期望值上)。如果我评论第一个,那么它会继续把它放在下一个。尝试任何,anyString参数匹配。
我看到它的方式,我嘲笑JdbcConnectionProperties loadProperties,所以我可以简化我的测试。然后我将一个模拟的Properties对象传递给测试。
然后...
...它应该工作。顺便说一句,我从来没有在异常块中看到这个数量级的异常。
谢谢。
你能解释一下为什么吗?因为它的同步(线程安全)?有没有可能导致此类问题的方法列表?我提供的解决方案非常简单且正确,但如果您有资源讨论提及的行为,这将有助于未来。谢谢。 – pfh
有一个列表,但它在代码中(参见'ExpectationsModifier'类)。原因在于,当JMockit嘲笑一个类时,它临时重新定义它在JVM中的字节码,影响所有实例和所有方法调用,而不管它们来自何处(实际上,在类加载期间过滤调用)。将来,这些类型的问题将通过对被测试(调用者)代码进行字节码修改而不是模拟代码来消除;但是我需要一段时间来实现它。 –