001 package com.mockrunner.jdbc; 002 003 import com.mockrunner.mock.jdbc.MockResultSet; 004 005 /** 006 * A <code>ResultSetFactory</code> implementation which will produce 007 * <code>MockResultSet</code> instances based on information given as 008 * <code>String</code> arrays. 009 * 010 * <p> 011 * <code>StringValuesTable</code> and <code>ArrayResultSetFactory</code> can 012 * provide easy set up of unit test fixtures and assertion of outcomes with the 013 * same data structures, without any need for external sources of test data: 014 * </p> 015 * 016 * <p> 017 * <pre> 018 * private static final String _SQL_SELECT_ALL_EMPLOYEES = 019 * "SELECT * FROM employee"; 020 * private StringValuesTable <b>_employeeQueryResults</b>; 021 * ArrayResultSetFactory <b>_arrayResultSetFactory</b>; 022 * private Employee[] _employees; 023 * 024 * protected void setUp() throws Exception { 025 * super.setUp(); 026 * <b>_employeeQueryResults</b> = new StringValuesTable( 027 * "employeeQueryResults", 028 * new String[] { 029 * "id", "lastname", "firstname", 030 * }, 031 * new String[][] { 032 * new String[] {"1", "gibbons", "peter"}, 033 * new String[] {"2", "lumbergh", "bill"}, 034 * new String[] {"3", "waddams", "milton"}, 035 * } 036 * ); 037 * _employees = new Employee[3] { 038 * new Employee( 039 * <b>_employeeQueryResults.getItem(1, "id")</b>, 040 * <b>_employeeQueryResults.getItem(1, "lastname")</b>, 041 * <b>_employeeQueryResults.getItem(1, "firstname")</b>, 042 * ), 043 * ... 044 * }; 045 * ... 046 * } 047 * 048 * public void testGetEmployees() throws Exception { 049 * PreparedStatementResultSetHandler preparedStatementResultSetHandler = 050 * getPreparedStatementResultSetHandler(); 051 * <b>_arrayResultSetFactory</b> = 052 * new ArrayResultSetFactory(<b>_employeeQueryResults</b>); 053 * MockResultSet resultSet = 054 * preparedStatementResultSetHandler.createResultSet( 055 * <b>_employeeQueryResults.getName()</b>, 056 * <b>arrayResultSetFactory</b>); 057 * preparedStatementResultSetHandler.prepareResultSet( 058 * _SQL_SELECT_ALL_EMPLOYEES, resultSet); 059 * 060 * // execute query, perhaps calling method on an EmployeeDAO... 061 * 062 * assertEquals( 063 * <b>_employeeQueryResults.getNumberOfRows()</b>, 064 * resultsList.size()); 065 * for (int i = 0; i < _employees.length; i++) { 066 * assertTrue(resultsList.contains(_employees[i])); 067 * } 068 * MockResultSet mockResultSet = 069 * preparedStatementResultSetHandler.getResultSet( 070 * SQL_SELECT_ALL_EMPLOYEES); 071 * int rows = mockResultSet.getRowCount(); 072 * for (int row = 1; row <= rows; row++) { 073 * verifyResultSetRow( 074 * <b>_employeeQueryResults.getName()</b>, 075 * row, <b>_employeeQueryResults.getRow(row)</b>); 076 * } 077 * verifySQLStatementExecuted(_SQL_SELECT_ALL_EMPLOYEES); 078 * verifyAllResultSetsClosed(); 079 * verifyAllStatementsClosed(); 080 * verifyConnectionClosed(); 081 * } 082 * </pre> 083 * </p> 084 * 085 * @author Erick G. Reid 086 */ 087 public class ArrayResultSetFactory implements ResultSetFactory 088 { 089 private String[] columnNames = new String[0]; 090 private String[][] stringMatrix = new String[0][0]; 091 092 /** 093 * Creates a new <code>ArrayResultSetFactory</code> that will produce 094 * result sets based on information in the given 095 * <code>StringValuesTable</code>. 096 * 097 * @param stringValuesTable the <code>StringValuesTable</code> to use. This argument 098 * cannot be <code>null</code>. 099 */ 100 public ArrayResultSetFactory(StringValuesTable stringValuesTable) 101 { 102 if (stringValuesTable != null) 103 { 104 this.stringMatrix = stringValuesTable.getStringMatrix(); 105 this.columnNames = stringValuesTable.getColumnNames(); 106 return; 107 } 108 throw new IllegalArgumentException("the string table cannot be null"); 109 } 110 111 /** 112 * Creates a new <code>ArrayResultSetFactory</code> with the given matrix 113 * for data representation. 114 * 115 * @param stringMatrix the data representation for the result sets this factory will 116 * produce. This argument cannot be <code>null</code>, must 117 * not contain any null values, and each array in the matrix must 118 * contain the same number of elements as the first (<code>stringMatrix[0].length == stringMatrix[n].length</code> 119 * for any given valid row number, <code>n</code>). Further, 120 * this matrix must, at a minimum represent <code>1</code> row 121 * and <code>1</code> column of items (<code>stringMatrix.length >= 1</code>, 122 * and <code>stringMatrix[0].length >= 1</code>). 123 */ 124 public ArrayResultSetFactory(String[][] stringMatrix) 125 { 126 this.stringMatrix = StringValuesTable.verifyStringMatrix(stringMatrix); 127 } 128 129 /** 130 * Creates a new <code>ArrayResultSetFactory</code> with the given set of 131 * column names and the given matrix for data representation. 132 * 133 * @param columnNames the column names for the result sets this factory will 134 * produce. This argument may be <code>null</code> if no column 135 * names are desired, but if a non-<code>null</code> array 136 * reference is given, the array cannot contain any 137 * <code>null</code> nor duplicate elements, and must have the 138 * same number of elements as there are columns in the given 139 * string matrix (<code>stringMatrix[n]</code> for any given 140 * valid row number, <code>n</code>). 141 * @param stringMatrix the data representation for the result sets this factory will 142 * produce. This argument cannot be <code>null</code>, must 143 * not contain any null values, and each array in the matrix must 144 * contain the same number of elements as the first (<code>stringMatrix[0].length == stringMatrix[n].length</code> 145 * for any given valid row number, <code>n</code>). Further, 146 * this matrix must, at a minimum represent <code>1</code> row 147 * and <code>1</code> column of items (<code>stringMatrix.length >= 1</code>, 148 * and <code>stringMatrix[0].length >= 1</code>). 149 */ 150 public ArrayResultSetFactory(String[] columnNames, String[][] stringMatrix) 151 { 152 this.stringMatrix = StringValuesTable.verifyStringMatrix(stringMatrix); 153 if (columnNames != null) 154 { 155 this.columnNames = StringValuesTable.verifyColumnNames(columnNames, stringMatrix); 156 } 157 } 158 159 /** 160 * Returns a <code>MockResultSet</code> with the given ID, containing 161 * values based on the elements given at construction. 162 * 163 * @param id the ID for the result set. This argument cannot be 164 * <code>null</code>. 165 */ 166 public MockResultSet create(String id) 167 { 168 if (id != null) 169 { 170 MockResultSet resultSet = new MockResultSet(id); 171 if (columnNames != null) 172 { 173 for (int ii = 0; ii < columnNames.length; ii++) 174 { 175 resultSet.addColumn(columnNames[ii]); 176 } 177 } 178 for (int jj = 0; jj < stringMatrix.length; jj++) 179 { 180 resultSet.addRow(stringMatrix[jj]); 181 } 182 return resultSet; 183 } 184 throw new IllegalArgumentException("the result set ID cannot be null"); 185 } 186 }