【问题标题】:How to use mockito for testing Database connection如何使用 mockito 测试数据库连接
【发布时间】:2015-02-19 20:32:57
【问题描述】:

我正在使用Junit 来测试我的球衣API。我想在没有数据库的情况下测试 DAO。我尝试使用 Mockito 但仍然无法使用模拟对象来测试包含对 DB 的 Hibernate 调用的 DAO。我想为调用 DAO 的 Helper 类编写 Junit。任何人都可以提供一些示例代码的解决方案来模拟 DAO 中的数据库连接。

编辑:

Status.java

@GET
@Produces(MediaType.TEXT_PLAIN)
public String getDBValue() throws SQLException {
    DatabaseConnectionDAO dbConnectiondao = new DatabaseConnectionDAO();
    String dbValue = dbConnectiondao.dbConnection();
    return dbValue;
}

DatabaseConnectionDAO.java

private Connection con;
private Statement stmt;
private ResultSet rs;
private String username;

public String dbConnection() throws SQLException{
    try{
        Class.forName("com.mysql.jdbc.Driver");
        con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root", "root");
        stmt = con.createStatement();
        rs =stmt.executeQuery("select * from test");

        while(rs.next()){
            username = rs.getString(1);             
        }           
    }catch(Exception e){
        e.printStackTrace();            
    }finally{
    con.close();    
    }
    return username;
}

TestDatabase.java

@Test
public void testMockDB() throws SQLException{
    DatabaseConnectionDAO mockdbDAO = mock(DatabaseConnectionDAO.class);
    Connection con = mock(Connection.class);
    Statement stmt = mock(Statement.class);
    ResultSet rs = mock(ResultSet.class);

    Client client = Client.create();
    WebResource webResource = client.resource("myurl");
    ClientResponse response = webResource.accept(MediaType.TEXT_PLAIN).get(ClientResponse.class);

    verify(mockdbDAO).dbConnection();

    //when(rs.next()).thenReturn(true);
    when(rs.getString(1)).thenReturn(value);    

    actualResult = response.getEntity(String.class);
    assertEquals(expectedResult,actualResult );
}

【问题讨论】:

  • 你能分享你的代码吗?

标签: junit jersey mockito jersey-client rest-assured


【解决方案1】:

我认为您可能错过了应该如何模拟 DAO 的想法。您不必担心任何连接。一般来说,你只想模拟发生了什么,当它的方法被调用时,比如findXxx 方法。例如,假设你有这个 DAO 接口

public interface CustomerDAO {
    public Customer findCustomerById(long id);
}

你可以嘲笑它

CustomerDAO customerDao = Mockito.mock(CustomerDAO.class);

Mockito.when(customerDao.findCustomerById(Mockito.anyLong()))
        .thenReturn(new Customer(1, "stackoverflow"));

然后,您必须将该模拟实例“注入”到依赖它的类中。例如,如果一个资源类需要它,你可以通过构造函数注入它

@Path("/customers")
public class CustomerResource {
    
    CustomerDAO customerDao;
    
    public CustomerResource() {}
    
    public CustomerResource(CustomerDAO customerDao) {
        this.customerDao = customerDao;
    }
    
    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response findCustomer(@PathParam("id") long id) {
        Customer customer = customerDao.findCustomerById(id);
        if (customer == null) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return Response.ok(customer).build();
    }
}

...

new CustomerResource(customerDao)

不,当您点击findCustomer 方法时,DAO 将始终在模拟的 DAO 中返回 Customer。

这是一个完整的测试,使用 Jersey 测试框架

public class CustomerResourceTest extends JerseyTest {

    private static final String RESOURCE_PKG = "jersey1.stackoverflow.standalone.resource";
    
    public static class AppResourceConfig extends PackagesResourceConfig {

        public AppResourceConfig() {
            super(RESOURCE_PKG);
            
            CustomerDAO customerDao = Mockito.mock(CustomerDAO.class);
            Mockito.when(customerDao.findCustomerById(Mockito.anyLong()))
                    .thenReturn(new Customer(1, "stackoverflow"));
           
            getSingletons().add(new CustomerResource(customerDao));
        }

    }

    @Override
    public WebAppDescriptor configure() {
        return new WebAppDescriptor.Builder()
                .initParam(WebComponent.RESOURCE_CONFIG_CLASS,
                        AppResourceConfig.class.getName()).build();
    }

    @Override
    public TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }
    
    @Test
    public void testMockedDAO() {
        WebResource resource = resource().path("customers").path("1");
        String json = resource.get(String.class);
        System.out.println(json);
    }
}

Customer 类是一个简单的 POJO,带有 long idString name。 Jersey 测试框架的依赖是

<dependency>
    <groupId>com.sun.jersey.jersey-test-framework</groupId>
    <artifactId>jersey-test-framework-grizzly2</artifactId>
    <version>1.19</version>
    <scope>test</scope>
</dependency>

更新

上面的示例使用 Jersey 1,因为我看到 OP 使用的是 Jersey 1。有关使用 Jersey 2(带有注解注入)的完整示例,请参阅this post

【讨论】:

  • 感谢您的建议。现在我很清楚这个想法,我会尝试一下。
【解决方案2】:

简短的回答只是不要

需要进行单元测试的代码是 DAO 的客户端,因此需要模拟的是 DAO。 DAO 是将应用程序与外部系统(此处为数据库)集成的组件,因此必须将它们作为集成测试(即使用真实数据库)进行测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    相关资源
    最近更新 更多