Mock ResultSet with Mockito - PullRequest
       7

Mock ResultSet with Mockito

0 голосов
/ 04 января 2019

Как смоделировать результат?

В тестовом классе пытаются смоделировать набор результатов, как показано ниже, но при попытке проверить получение ошибки как UnnecessaryStubbingException в утверждениях:

voObj.setDept(rs.getString(2)); 

и

voObj.setDeptDesc(rs.getString(3));

Есть предложения о том, как смоделировать результат?

public class Example { 
    public static void main(String[] s) {
        method1();
        method2();
        ..........
    }

    private Employee method1(String str) {
                Connection conn           =  getConnection();   
        PreparedStatement pstmt   = null;
        .........
        pstmt = conn.prepareStatement(strQuery.toString());
        rs  = pstmt.executeQuery();
        int ilCounter   = 0; 
        int maxId   = method2(loc); //some DB calls here with select

        if(null != rs) {            
            while(rs.next()) { 
                ilCounter++;
                ObjVoBean voObj = new ObjVoBean();
                voObj.setLoc(rs.getString(1));
                voObj.setDept(rs.getString(2));
                voObj.setDeptDesc(rs.getString(3));
            }
            .................
        }
       }

   private Employee method2(String str1) {
                Connection connOHM      = getConnection();  
        PreparedStatement pstmt     = null;
        .........
       //some DB call with select ...
   }
}

public class ExampleTest { 
   @InjectMocks
   Example example;

   @Mock
   private Connection c;

   @Mock
   private PreparedStatement preStmt;
    .....

   @Before
   public void setUp() {
        ........
   }

   @Test
   public void testMethod1() throws SQLException {
        ResultSet resultSetMock = Mockito.mock(ResultSet.class);
        when(resultSetMock.getString(1)).thenReturn("1111");
        when(resultSetMock.getString(2)).thenReturn("2222");
        when(resultSetMock.getString(3)).thenReturn("dept desc");

        when(c.prepareStatement(any(String.class))).thenReturn(preStmt);
        when(resultSetMock.next()).thenReturn(true).thenReturn(false); 
        doReturn(resultSetMock).when(preStmt).executeQuery();

        example.method1("1111");            
        assertTrue(true);
   }
}

1 Ответ

0 голосов
/ 04 января 2019

Чтобы иметь возможность смоделировать ResultSet, вы должны смоделировать все объекты, которые позволяют создать его, то есть Connection, который создает PreparedStatement, который сам создает ResultSet. Mocking the Connection будет работать в протестированном коде, только если вы предоставите способ установить соединение из клиентского кода.

Здесь conn, то есть Соединение должно быть сначала введено как зависимость в вашем тестовом приспособлении:

pstmt = conn.prepareStatement(strQuery.toString());

Обычно вы создаете Connection, например:

conn = DriverManager.getConnection(DB_URL,USER,PASS);

или через DataSource, например:

conn = ds.getConnection();

Таким образом, вы должны абстрагировать эту часть в интерфейс или не конечный класс и определить реализацию, которая выполняет эту обработку. Таким образом, вы можете смоделировать часть, которая создает соединение. И поэтому вы можете смоделировать всю цепочку: Connection-PreparedStatement-ResultSet.


Лично я бы избегал этого, потому что издеваться над многими вещами часто не правильный выбор.
В вашем случае вам нужно смоделировать ResultSet, чтобы протестировать постобработку после загрузки ResultSet:

while(rs.next()) { 
     ilCounter++;
     ObjVoBean voObj = new ObjVoBean();
     voObj.setLoc(rs.getString(1));
     voObj.setDept(rs.getString(2));
     voObj.setDeptDesc(rs.getString(3));
}

Таким образом, в качестве альтернативы вы можете переместить весь код, выполненный ранее, в метод определенного класса, обрабатывающий часть персистентности. Таким образом, вам просто нужно смоделировать эту зависимость и этот метод. Вам не нужно беспокоиться о подключении и любых деталях JDBC.

EmployeeDAO employeeDAO; // dependency to mock

// constructor with dependency
public Example(EmployeeDAO employeeDAO){
  this.employeeDAO = employeeDAO;
}

private Employee method1(String str) {
   ResultSet resultSet = employeeDAO.load(str);

    if(null != rs) {            
        while(rs.next()) { 
            ilCounter++;
            ObjVoBean voObj = new ObjVoBean();
            voObj.setLoc(rs.getString(1));
            voObj.setDept(rs.getString(2));
            voObj.setDeptDesc(rs.getString(3));
        }
        .................
    }
   }

Конечно, компоненты DAO также должны быть подвергнуты однократным испытаниям.
Но, как уже говорилось ранее, утверждение, что Connection создано или что оно возвращает PreparedStatement, не приносит значения. Тестирование того, что ваши запросы выполняют то, что вы ожидаете от них, намного интереснее с точки зрения функционального охвата.
В этом случае вы хотите проверить его на базе данных в памяти, такой как H2, потому что модульные тесты не являются интеграционными тестами, а модульные тесты должны выполняться быстро.
Для написания тестов DAO / Repository, Dbunit и DbSetup являются хорошими кандидатами, поскольку они предоставляют возможности для настройки БД перед каждым тестом (в основном ввод данных и очистка данных).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...