异常块上的 JMockit NullPointerException?

发布于 2024-12-06 18:40:49 字数 5078 浏览 0 评论 0原文

我已经在这个测试上花费了大量时间并且无法推理出它的出路,我别无选择,只能寻求你的帮助:)

使用 JMockit 来测试我自己的一些 JDBC“包装器”类,我来到了一个死胡同。

这是测试类:

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)

该类非常简单。测试应该非常简单。但不知何故,测试在期望块上崩溃(在第一个属性期望上)。如果我评论第一个,那么它会继续将其扔到下一个。尝试过any,anyString 进行参数匹配。

在我看来,我模拟了 JdbcConnectionProperties loadProperties,这样我就可以简化我的测试。然后我将一个模拟的 Properties 对象传递到测试中。

然后...

...它应该可以工作。 顺便说一句,我从未在 Exceptions 块中看到过如此严重的异常。

谢谢。

Having already spent a lot of time on this test and unable to reason my way out of it, i have no other choice than ask for your help :)

Using JMockit to test some of my own JDBC "Wrapper" classes, i came to a dead end.

This is the class im testing:

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;
    }
}

This is the test:

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());
    }
}

A couple of notes. I tried forsing the mocked properties into the object with Deencapsulation(i left them commented in the code).

I tried just mocking it with the @Mocked annotation.

I tried stubing it with stubOutClass.

This is not a first test i am writing, but im relativly new to JMockit.
The tests i wrote before never caused me headaches like this one. I think i wrote about 20 - 30 tests with JMockit and never had problems like this.

The error is(in all the mentioned scenarios) :

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)

The class is very simple. The test should be very simple. But somehow the test crashes on the Expectations block(on the first properties expectation). If I comment the first ones, then it continues to throw it on next one. Tried any, anyString for argument matching.

The way I see it, i mock the JdbcConnectionProperties loadProperties so i can simplify my testing. Then i pass a mocked Properties object into the test.

And then...

...it should work.
BTW, I never saw an exception of this magnitude in a Exceptions block.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

裸钻 2024-12-13 18:40:49

Hashtable#get 是 JMockit 默认情况下不模拟的少数方法之一,因为它在模拟时可能会干扰 JDK 或 JMockit 本身。您可以通过使用 @Mocked("get") 显式请求对其进行模拟来使此特定测试正常工作。

不过,在测试中使用实际的“.properties”文件可能会更简单,而不进行任何模拟。

Hashtable#get is one of a few methods not mocked by default by JMockit, because it can interfere with the JDK or with JMockit itself when mocked. You can get this particular test to work by explicitly asking for it to be mocked, with @Mocked("get").

It might be simpler to just use an actual ".properties" file in the test, though, with no mocking.

夏尔 2024-12-13 18:40:49
new Expectations() {
            @Mocked("getProperty")
            Properties properties;

            {
                properties.getProperty("user");
                result = username;

                properties.getProperty("password");
                result = password;

                properties.getProperty("connection_type");
                result = connectionType;

                properties.getProperty("server_address");
                result = serverAddress;

                properties.getProperty("port");
                result = port;

                properties.getProperty("sid");
                result = sid;
            }
        };

谢谢罗杰里奥。正如他指出的,原因是“内部”阶级的嘲笑。需要记住一个非常小的限制。

其他需要注意的类是(我希望我可以写这个):

使用 JMockit 进行模拟时要记住的类

new Expectations() {
            @Mocked("getProperty")
            Properties properties;

            {
                properties.getProperty("user");
                result = username;

                properties.getProperty("password");
                result = password;

                properties.getProperty("connection_type");
                result = connectionType;

                properties.getProperty("server_address");
                result = serverAddress;

                properties.getProperty("port");
                result = port;

                properties.getProperty("sid");
                result = sid;
            }
        };

Thanks Rogerio. As he pointed out, the reason is the "internal" class mocking. A very small limitation to have in mind.

The other classes that require some attention are(i hope i can write this):

Classes to have in mind while mocking with JMockit

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文