web-dev-qa-db-ja.com

データベース接続をテストするためにmockitoを使用する方法

ジャージAPIをテストするためにJunitを使用しています。データベースなしでDAOをテストしたい。 Mockitoを使用しようとしましたが、DBへのHibernate呼び出しを含むDAOをテストするためにモックオブジェクトを使用できません。 DAOを呼び出すヘルパークラス用にJunitを記述したいと思います。DAOでDB接続をモックするためのサンプルコードを使用して、ソリューションを提供できる人はいますか。

編集:

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 );
}
5
Jugi

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で顧客を返します。

これがJerseyTestFrameworkを使用した完全なテストです

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クラスは、long idString nameを持つ単純なPOJOです。ジャージーテストフレームワークの依存関係は

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

更新

上記の例では、OPがJersey 1を使用していることを確認したので、Jersey 1を使用しています。Jersey2(アノテーションインジェクションあり)を使用した完全な例については、 この投稿 を参照してください。

19
Paul Samsotha

短い答えだけしないでください

単体テストが必要なコードはDAOのクライアントであるため、モックする必要があるのはDAOです。 DAOは、アプリを外部システム(ここではデータベース)と統合するコンポーネントであるため、統合テストとして(つまり、実際のデータベースで)テストする必要があります。

7
Brice