在已經花了很多時間在這個測試並不能對我這樣推理出來的,我沒有別的選擇,而不是找你幫忙:)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中的字節碼,影響所有實例和所有方法調用,而不管它們來自何處(實際上,在類加載期間過濾調用)。將來,這些類型的問題將通過對被測試(調用者)代碼進行字節碼修改而不是模擬代碼來消除;但是我需要一段時間來實現它。 –