【问题标题】:Mockito Test - Test write() method leads to NullPointerException [duplicate]Mockito 测试 - 测试 write() 方法导致 NullPointerException [重复]
【发布时间】:2020-04-01 10:38:25
【问题描述】:

基于示例 here,我尝试为我的方法 write() 创建一个单元测试,该方法基本上获取一个对象并将其保存到我的 SQLite DB 中。

我收到此错误:

在下面的代码中,这两行已用“错误”一词进行了注释。

1) 与数据库的连接

public class DBAdapter {

    public Connection getConnection() throws WebApplicationException {
        try {
            Context ctx = new InitialContext();
            DataSource ds = (DataSource) 
            ctx.lookup("java:/comp/env/jdbc/escapeconnect");
            Connection con = ds.getConnection();
            Statement st = con.createStatement();
            st.execute("PRAGMA foreign_keys=on;");
            st.close();
            return con;
        } catch (NamingException e) {
            e.printStackTrace();
            throw new WebApplicationException(e.getMessage());
        } catch (SQLException e) {
            e.printStackTrace();
            throw new WebApplicationException(e.getMessage());
        }       
    }
}

2) 获取对象并将其插入数据库的类

public class DAOpanel implements DAOpanelIF {

    DBAdapter dbAdapter = new DBAdapter();

    @Override
    public int write(PanelDAOBean panel) {

        String query = "";

        if(panel.getId()<1) {
            query = "INSERT INTO panel (name,device_mac) VALUES(?,?)";

            try (Connection con = dbAdapter.getConnection();
                    PreparedStatement pstm = con.prepareStatement(query);){ // ERROR
                pstm.setString(1, panel.getName());             
                pstm.setString(2, panel.getDevice_mac());

                int rowsAffected = pstm.executeUpdate();
                if(rowsAffected==1) {
                    ResultSet rs = pstm.getGeneratedKeys();
                    if(rs.next()) {
                        return rs.getInt(1);
                    }
                }
                pstm.close();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new WebApplicationException(e.getMessage());
            }
        }else {
            query = "UPDATE panel SET name = ?, device_mac = ? WHERE id = ?";

            try (Connection con = dbAdapter.getConnection();
                    PreparedStatement pstm = con.prepareStatement(query);){
                pstm.setString(1, panel.getName());             
                pstm.setString(2, panel.getDevice_mac());
                pstm.setInt(3, panel.getId());
                pstm.executeUpdate();
                pstm.close();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new WebApplicationException(e.getMessage());
            }
        }
        return -1;
    }

3)DAOpanel类的write()方法测试

@ExtendWith(MockitoExtension.class)
class TestDaoPanel {

  PanelDAOBean panelForTest = new PanelDAOBean();

  @InjectMocks private DAOpanel daoPanel;

  @Mock private DBAdapter dbAdapter;

  @Mock private Connection con;

  @Mock private PreparedStatement pstm;

  @Before
  public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
    panelForTest.setName("Panel Unit Test");
    panelForTest.setDevice_mac("FF:FF:FF:FF:FF:FF");

    when(con.prepareStatement(Mockito.any())).thenReturn(pstm);
    when(dbAdapter.getConnection()).thenReturn(con);
  }

  /**
   * Test method for {@link
   * main.java.ch.ffhs.pa5.escapeconnect.persistency.DAOpanel#write(PanelDAOBean)}.
   */
  @Test
  void testWrite() {
    daoPanel.write(panelForTest); // ERROR
  }

4) 插入数据库的对象

public class PanelDAOBean {
    private int id = 0;
    private String name;
    private String device_mac;
    public PanelDAOBean() {
        super();
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDevice_mac() {
        return device_mac;
    }
    public void setDevice_mac(String device_mac) {
        this.device_mac = device_mac;
    }

}

感谢您的帮助。

【问题讨论】:

  • 这应该是实例级别DBAdapter dbAdapter = new DBAdapter();
  • DaoPanel 应该有一个 DBAdapter 的初始化构造函数,以便 @InjectMocks 工作
  • @HakanDilek:我不确定我是否关注你。你的意思是这样的吗? public DAOpanel(DBAdapter myadapter)
  • 使用@BeforeEach 而不是@Before。最后一个是 Junit4 而第一个是 JUnit 5 语法。因此,您的 setUp 方法没有被执行。

标签: java unit-testing mockito dao


【解决方案1】:

你的问题在下面一行

    public class DAOpanel implements DAOpanelIF {

        DBAdapter dbAdapter = new DBAdapter();
        ...
}

你在嘲笑DBAdapter,但没有将它注入DAOpanel。你可以添加一个接受DAOpanel的构造函数

public class DAOpanel implements DAOpanelIF {
   priavte final DBAdapter dbAdapter;
   public DAOpanel(DBAdapter dbAdapter) {
      this.dbAdapter = dbAdapter;
   }
}

当您使用@Mock & @InjectMock 时,依赖将自动注入到构造函数中。

【讨论】:

  • 感谢您抽出宝贵时间。我仍然有同样的错误:/
  • 您可以发布您在进行上述更改后获得的堆栈跟踪吗?
  • @YogeshBadke:如果只存在默认构造函数 FieldInjection 将被使用。问题出在注释上(见我上面的评论)。
猜你喜欢
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
  • 1970-01-01
  • 2017-02-25
  • 1970-01-01
相关资源
最近更新 更多