Ответ 1
Вы также должны издеваться над методом next(), чтобы он возвращал true при первом вызове, поскольку mockito будет возвращать false по умолчанию.
Mockito.when(resultSetMock.next()).thenReturn(true).thenReturn(false);
У меня есть код, где я заполняю Resultset с помощью CallableStatement.executeQuery(). Я высмеивал ResultSet и CallableStatement, но для проверки метода я должен заполнить ResultSet.
Вот код из метода, который я тестирую
ResultSet rset = cs.executeQuery();
while (rset.next()) {
IndexVolatilityImpl tsImpl = new IndexVolatilityImpl();
tsImpl.setTradeDate(rset.getString("trade_date"));
tsImpl.setTradeTime(rset.getString("trade_time"));
tsImpl.setExprDate(rset.getString("expr_date"));
tsImpl.setSymbol(rset.getString("symbol"));
tsImpl.setTradePrice(rset.getDouble("trade_price"));
tsImpl.setContractMonth(rset.getString("contract_month"));
tsImpl.setMilliSecs(rset.getString("trade_time_thou"));
colIndexVolatilityImpl.add(tsImpl);
Я издевался над CallableStatement и ResultSet, так как они издеваются над моим номером. Я хотел бы заполнить Resultset и сделать это как ниже
resultSetMock = Mockito.mock(ResultSet.class);
Mockito.when(resultSetMock.getString("trade_date")).thenReturn("03/10/2011");
Mockito.when(resultSetMock.getString("trade_time")).thenReturn("12:24:56");
Mockito.when(resultSetMock.getString("expr_date")).thenReturn("03/19/2011");
Mockito.when(resultSetMock.getString("symbol")).thenReturn("VIX1");
Mockito.when(resultSetMock.getDouble("trade_price")).thenReturn(Double.valueOf("20.96"));
Mockito.when(resultSetMock.getString("contract_month")).thenReturn("1");
Mockito.when(resultSetMock.getString("trade_time_thou")).thenReturn("165");
Mockito.doReturn(resultSetMock).when(callableStatementMock).executeQuery();
Но результат выводит значение null.
Итак, любая помощь будет оценена, чтобы помочь заполнить посмеянный набор результатов.
Спасибо Tejas
Вы также должны издеваться над методом next(), чтобы он возвращал true при первом вызове, поскольку mockito будет возвращать false по умолчанию.
Mockito.when(resultSetMock.next()).thenReturn(true).thenReturn(false);
Я написал что-то для этого же случая. Вы можете издеваться над набором результатов с помощью Mockito. Вы можете также петли над макетными строками набора результатов, высмеивая resultet.next() с помощью этого фрагмента кода.
// two dimensional array mocking the rows of database.
String[][] result = { { "column1", "column2" }, { "column1", "column2" } };
@InjectMocks
@Spy
private TestableClass testableClass;
@Mock
private Connection connection;
@Mock
private Statement statement;
@Mock
private ResultSet resultSet;
@BeforeTest
public void beforeTest() {
MockitoAnnotations.initMocks(this);
}
@BeforeMethod
public void beforeMethod() throws SQLException {
doAnswer(new Answer<Connection>() {
public Connection answer(InvocationOnMock invocation)
throws Throwable {
return connection;
}
}).when(testableClass).getConnection();
when(connection.createStatement()).thenReturn(statement);
when(statement.executeQuery(anyString())).thenReturn(resultSet);
final AtomicInteger idx = new AtomicInteger(0);
final MockRow row = new MockRow();
doAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
int index = idx.getAndIncrement();
if (result.length <= index) {
return false;
}
String[] current = result[index];
row.setCurrentRowData(current);
return true;
}
;
}).when(resultSet).next();
doAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
int idx = ((Integer) args[0]).intValue();
return row.getColumn(idx);
}
;
}).when(resultSet).getString(anyInt());
}
static class MockRow {
String[] rowData;
public void setCurrentRowData(String[] rowData) {
this.rowData = rowData;
}
public String getColumn(int idx) {
return rowData[idx - 1];
}
}
Я переписал @karthik m немного ответить, чтобы сделать издевку ResultSet автономной:
Используя следующий класс, я могу легко экспортировать результат из запроса как csv и написать тест вокруг этого.
Не все методы из ResultSet издеваются, поскольку они мне не нужны, но они должны быть довольно тривиальными в использовании.
import no.di.common.util.StringUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.File;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
/**
* Creates a Mock of a ResultSet
*/
public class ResultSetMocker {
private Map<String, Integer> columnNames = new HashMap<>();
private Object[][] result;
public ResultSetMocker(String filename) throws IOException {
loadData(filename);
}
private void loadData(String filename) throws IOException {
List<Object[]> toRet = new ArrayList<>();
int numberOfParts = 0;
LineIterator it = FileUtils.lineIterator(new File(filename), "ISO8859-1");
try {
String names = it.nextLine();
String[] name = names.split(";");
for(int i = 0; i < name.length; i++) {
columnNames.put(name[i], i + 1);
}
while (it.hasNext()) {
String line = it.nextLine();
String[] parts = line.split(";");
numberOfParts = parts.length;
Object[] result = new Object[parts.length];
for(int i = 0; i < parts.length; i++) {
if(parts[i].equals("(null)"))
result[i] = null;
else if(StringUtil.isAllNumeric(parts[i]))
result[i] = Integer.parseInt(parts[i]);
else
result[i] = parts[i];
}
toRet.add(result);
}
} finally {
it.close();
}
result = toRet.toArray(new Object[toRet.size()][numberOfParts]);
}
public ResultSet getResultSet() throws SQLException, IOException {
ResultSet resultSet = mock(ResultSet.class);
final AtomicInteger idx = new AtomicInteger(0);
final MockRow row = new MockRow(columnNames);
doAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
int index = idx.getAndIncrement();
if (result.length > index) {
row.setCurrentRowData(result[index]);
return true;
} else
return false;
}
}).when(resultSet).next();
doAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
int idx = (Integer) args[0];
return row.getString(idx);
}
}).when(resultSet).getString(anyInt());
doAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String name = (String) args[0];
return row.getString(name);
}
}).when(resultSet).getString(anyString());
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String name = (String) args[0];
return row.getObject(name);
}
}).when(resultSet).getObject(anyString());
doAnswer(new Answer<Integer>() {
@Override
public Integer answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String name = (String) args[0];
return row.getInt(name);
}
}).when(resultSet).getInt(anyString());
return resultSet;
}
static class MockRow {
Object[] rowData;
private Map<String, Integer> columnNames;
public MockRow(Map<String, Integer> columnNames) {
this.columnNames = columnNames;
}
public void setCurrentRowData(Object[] rowData) {
this.rowData = rowData;
}
public String getString(int idx) {
return (String)rowData[idx - 1];
}
public String getString(String name) {
return (String)rowData[columnNames.get(name) - 1];
}
public Object getObject(String name) {
return rowData[columnNames.get(name) - 1];
}
public Integer getInt(String name) {
return (Integer)rowData[columnNames.get(name) - 1];
}
}
}