【问题标题】:PowerMock a static method inside another static methodPowerMock 在另一个静态方法中的静态方法
【发布时间】:2020-12-18 05:12:03
【问题描述】:

我有以下代码

    import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
public class DatabaseReader {
 
    public static final String CONNECTION = "jdbc:mysql://localhost/testdb";
     
    public static String getById(Integer id) throws SQLException {
        String query = "SELECT * FROM Foo WHERE Id = ?";
        Connection connection = DriverManager.getConnection(CONNECTION);
        PreparedStatement preparedStatement = connection.prepareStatement(query);
        preparedStatement.setInt(1, id);
        ResultSet resultSet = preparedStatement.executeQuery();
         
        resultSet.next();
         
        String result = resultSet.getString(0);
         
        resultSet.close();
        preparedStatement.close();
        connection.close();
         
        return result;
    }
    
    public static String getId(int id) throws SQLException{
        return getById(id); 
    }
}

是否可以对函数 getById 进行 powermock,以便在测试 getId 时获得 getById 的模拟值? 我正在尝试这个:

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
 
import java.sql.SQLException;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
    
@RunWith(PowerMockRunner.class)
    @PrepareForTest(DatabaseReader.class)
    public class DatabaseReaderTest {
     
        @Test
        public void testGetById() {
            int inputId = 1;
            String returnValue = "JavaCodeGeeks";
     
            mockStatic(DatabaseReader.class);
     
            try {
                when(DatabaseReader.getById(inputId))
                    .thenReturn(returnValue);
                String actual = DatabaseReader.getId(inputId);
                System.out.println(actual);
                verifyStatic();
                assertEquals(returnValue, actual);
            } catch (SQLException e) {
                fail("No exception should be thrown.");
            }
        }

但是,当我打电话时它不起作用

String actual = DatabaseReader.getId(inputId);

它尝试调用整个数据库方法。 我对 IU 是否可以从静态方法模拟静态方法调用感到困惑。

【问题讨论】:

  • getId 是一个非常简单的方法,我不会费心去测试它。另一方面,如果 executeQuery 抛出异常,最好进行测试以检查 getById 是否不会泄漏连接。
  • 我想了解我们是否可以使用 powermock api 测试从另一个静态方法内部调用的静态方法。
  • 请将您的导入添加到您问题中的测试代码中。

标签: java junit mocking mockito powermock


【解决方案1】:

我认为你不应该这样测试。

Object under test 永远不能成为您的模拟对象(根据 PowerMock 的 PreparedForTest),您应该测试真正的代码,而不是“增强模拟能力”的东西可能会或可能不会表现就像一个真正的代码。

Mocks(甚至是由 Power mock 管理的那些)旨在模仿“依赖项”的行为。

现在每个代码都是可单元测试的,因此有时如果您希望对其进行正确测试,则应该对其进行修改:使用依赖注入(基本上与 make-everything-static 不兼容)方法,通常用于更好的依赖关系分离等等。

总的来说,Power Mock 是一个我们永远不应该使用的工具(好吧,这可能是主观的,但除了我自己的观点之外,我从各种不同的资源中听到了这种说法),除非我们可能正在谈论一些遗留系统。

所以底线,一般建议是:摆脱静态方法并重构。如果这是出于教育目的,并且您真的想学习 PowerMock:

不要“触摸”DatabaseReader 类(阅读,不要使用 power mock 增强它/更改它的字节码)

改为模拟 DriverManager (PowerMock)、Connection (Mockito/EasyMock/whatever)、PreparedStatement(Mockito/EasyMock/whatever) 和 ResultSet (Mockito/EasyMock/whatever)

【讨论】:

    【解决方案2】:

    您正在使用模拟 when。您需要使用org.powermock.api.mockito.PowerMockito.when

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-28
      • 1970-01-01
      • 2022-11-18
      • 2019-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多