using System;
using System.Data;
using DotNetMock;
namespace DotNetMock.Framework.Data{
/// <summary>
/// This Mock Object implements the IDataReader interface.
/// </summary>
public class MockDataReader : MockObject, IDataReader
{
private int _recordsAffectedCount = -1;
private int _expectedDepth = 0;
private bool _isClosed = false;
private ExpectationCounter _closeCalls = new ExpectationCounter("MockDataReader.CloseCalls");
private ExpectationCounter _readCalls = new ExpectationCounter("MockDataReader.ReadCalls");
private ExpectationCounter _nextResultCalls = new ExpectationCounter("MockDataReader.NextResultCalls");
private IDbConnection _currentConnection = null;
private bool _shouldCloseConnectionOnReaderClose = false;
private DataTable _schemaTable = null;
private object[,] _rows = new object[0,0];
private int _currentRow = -1;
private Exception _getException = null;
/// <summary>
/// Create mock implementation of <see cref="IDataReader"/>.
/// </summary>
public MockDataReader() {}
/// <summary>
/// Create named mock implementation of <see cref="IDataReader"/>.
/// </summary>
public MockDataReader( string mockName ) : base(mockName)
{
}
#region Mock Methods
/// <summary>
/// Sets the expected number of NextResult calls that will be made on the object.
/// </summary>
/// <param name="calls"></param>
public void SetExpectedNextResultCalls( int calls )
{
_nextResultCalls.Expected = calls;
}
/// <summary>
/// Sets the expected value to return for the Depth property.
/// </summary>
/// <param name="depth">Depth to return</param>
public void SetExpectedDepth( int depth )
{
_expectedDepth = depth;
}
/// <summary>
/// Set records affected count to return from RecordsAffected property
/// </summary>
/// <param name="count">Count to expect</param>
public void SetRecordsAffectedCount(int count)
{
_recordsAffectedCount = count;
}
/// <summary>
/// Set number of Close() calls to expect
/// </summary>
/// <param name="calls">Count to expect</param>
public void SetExpectedCloseCalls(int calls)
{
_closeCalls.Expected = calls;
}
/// <summary>
/// Sets Schema Table to used
/// </summary>
/// <param name="schemaTable">DataTable to describe columns</param>
public void SetSchemaTable(DataTable schemaTable)
{
_schemaTable = schemaTable;
}
/// <summary>
/// Set number of Read() calls to expect
/// </summary>
/// <param name="readCalls">Count to expect</param>
public void SetExpectedReadCalls(int readCalls)
{
_readCalls.Expected = readCalls;
}
/// <summary>
/// Set value of IsClosed property
/// </summary>
/// <param name="isClosed">True/False</param>
public void SetIsClosedValue(bool isClosed)
{
_isClosed = isClosed;
}
/// <summary>
/// Set data to use for all get calls
/// </summary>
/// <param name="rows">Two-Dimensional array to read data from. Format: [Row,Column]</param>
public void SetRows(object[,] rows)
{
_rows = rows;
}
/// <summary>
/// Set exception to throw on any GetXXX() calls
/// </summary>
/// <param name="exception">Exception to throw</param>
public void SetGetException(Exception exception)
{
_getException = exception;
}
#endregion
#region Internal Properties
internal IDbConnection Connection
{
set { _currentConnection = value; }
}
internal bool ShouldCloseConnectionOnReaderClose
{
set { _shouldCloseConnectionOnReaderClose = value; }
}
#endregion
#region Implementation of IDataReader
/// <summary>
/// <see cref="IDataReader.Close"/>
/// </summary>
public void Close()
{
_closeCalls.Inc();
_isClosed = true;
if ( _shouldCloseConnectionOnReaderClose )
{
if ( _currentConnection != null )
{
_currentConnection.Close();
}
}
}
/// <summary>
/// Gets SchemaTable
/// </summary>
/// <returns></returns>
public System.Data.DataTable GetSchemaTable()
{
return _schemaTable;
}
/// <summary>
/// Advances the data reader to the next result, when reading the result batch SQL statements
/// </summary>
/// <returns>Flag indicating if there are more rows or not.</returns>
public bool NextResult()
{
_nextResultCalls.Inc();
return innerExecute();
}
/// <summary>
/// Advances the IDataReader to the next record.
/// </summary>
/// <returns>Flag indicating if there are more rows to read</returns>
public bool Read()
{
_readCalls.Inc();
return innerExecute();
}
/// <summary>
/// Gets a value indicating the depth of nesting for the current row.
/// </summary>
public int Depth
{
get
{
return _expectedDepth;
}
}
/// <summary>
/// Gets a value indicating whether the data reader is closed
/// </summary>
public bool IsClosed
{
get
{
return _isClosed;
}
}
/// <summary>
/// Gets the number of rows changed, inserted, or deleted by executing the SQL statement
/// </summary>
public int RecordsAffected
{
get
{
return _recordsAffectedCount;
}
}
#region Implementation of IDataRecord
/// <summary>
/// Gets the 32-bit signed integer value of the specified field
/// </summary>
/// <param name="i">Index of the field to find</param>
/// <returns>The 32-bit signed integer value of the specified field.</returns>
public int GetInt32(int i)
{
return Convert.ToInt32(GetValue(i));
}
/// <summary>
/// Returns the value of the specified field
/// </summary>
/// <param name="i">Index of the field to find</param>
/// <returns>The Object which will contain the field value upon return.</returns>
public object GetValue(int i)
{
if (_getException != null)
{
throw _getException;
}
return _rows[_currentRow, i];
}
/// <summary>
/// Return whether the specified field is set to null
/// </summary>
/// <param name="i">Index of the field to find</param>
/// <returns>true if the specified field is set to null, otherwise false.</returns>
public bool IsDBNull(int i)
{
if (GetValue(i).GetType().Equals(typeof(DBNull)))
{
return true;
}
return false;
}
/// <summary>
/// Reads a stream of bytes from the specified column offset into the buffer as an array, starting at the given buffer offset. Currently Not Implemented
/// </summary>
/// <param name="i">The zero-based column ordinal. </param>
/// <param name="fieldOffset">The index within the field from which to begin the read operation. </param>
/// <param name="buffer">The buffer into which to read the stream of bytes.</param>
/// <param name="bufferoffset">The index for buffer to begin the read operation.</param>
/// <param name="length">The number of bytes to read.</param>
/// <returns>The actual number of bytes read.</returns>
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
this.NotImplemented("MockDataReader.GetBytes");
return 0;
}
/// <summary>
/// Gets the 8-bit unsigned integer value of the specified column.
/// </summary>
/// <param name="i">The zero-based column ordinal.</param>
/// <returns>The 8-bit unsigned integer value of the specified column.</returns>
public byte GetByte(int i)
{
return Convert.ToByte(GetValue(i));
}
/// <summary>
/// Gets the Type information corresponding to the type of Object that would be returned from GetValue. Currently Not Implemented
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The Type information corresponding to the type of Object that would be returned from GetValue.</returns>
public System.Type GetFieldType(int i)
{
if ( _schemaTable == null )
{
throw new DotNetMockException( "To use the GetFieldType method, a SchemaTable of type DataTable must be provided. Create a DataTable and use the SetSchemaTable method.");
}
return _schemaTable.Columns[i].DataType;
}
/// <summary>
/// Gets the fixed-position numeric value of the specified field.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The fixed-position numeric value of the specified field.</returns>
public decimal GetDecimal(int i)
{
return Convert.ToDecimal(GetValue(i));
}
/// <summary>
/// Gets all the attribute fields in the collection for the current record.
/// </summary>
/// <param name="values">An array of Object to copy the attribute fields into. </param>
/// <returns>The number of instances of Object in the array.</returns>
public int GetValues(object[] values)
{
int objectCounter = 0;
for ( int i = 0; i < values.GetLength(0); i++ )
{
if ( i < _rows.GetLength(1) )
{
objectCounter++;
values[i] = _rows[_currentRow, i];
}
}
return objectCounter;
}
/// <summary>
/// Gets the name for the field to find. Currently Not Implemented
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The name of the field or the empty string (""), if there is no value to return.</returns>
public string GetName(int i)
{
if ( _schemaTable == null )
{
throw new AssertionException( "Cannot process DataRecord with first setting schema using SetSchemaTable()" );
}
if ( i + 1 > FieldCount )
{
throw new IndexOutOfRangeException( "Index supplied: " + i + " was out of range for this DataRecord. FieldCount: " + FieldCount );
}
return _schemaTable.Columns[i].ColumnName;
}
/// <summary>
/// Gets the 64-bit signed integer value of the specified field.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The 64-bit signed integer value of the specified field.</returns>
public long GetInt64(int i)
{
return Convert.ToInt64(GetValue(i));
}
/// <summary>
/// Gets the double-precision floating point number of the specified field.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The double-precision floating point number of the specified field.</returns>
public double GetDouble(int i)
{
return Convert.ToDouble(GetValue(i));
}
/// <summary>
/// Gets the value of the specified column as a Boolean.
/// </summary>
/// <param name="i">The zero-based column ordinal. </param>
/// <returns>The value of the column.</returns>
public bool GetBoolean(int i)
{
return Convert.ToBoolean(GetValue(i));
}
/// <summary>
/// Returns the guid value of the specified field.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The guid value of the specified field.</returns>
public System.Guid GetGuid(int i)
{
return (Guid) GetValue(i);
}
/// <summary>
/// Gets the date and time data value of the spcified field.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The date and time data value of the spcified field.</returns>
public System.DateTime GetDateTime(int i)
{
return Convert.ToDateTime(GetValue(i));
}
/// <summary>
/// Return the index of the named field.
/// </summary>
/// <param name="name">The name of the field to find. </param>
/// <returns>The index of the named field.</returns>
public int GetOrdinal(string name)
{
if ( _schemaTable == null )
{
throw new AssertionException( "Cannot process DataRecord with first setting schema using SetSchemaTable()" );
}
for ( int counterCaseSensitive = 0; counterCaseSensitive < _schemaTable.Columns.Count; counterCaseSensitive++ )
{
if ( _schemaTable.Columns[counterCaseSensitive].ColumnName.Equals( name ) )
{
return counterCaseSensitive;
}
}
for ( int counterCaseInSensitive = 0; counterCaseInSensitive < _schemaTable.Columns.Count; counterCaseInSensitive++ )
{
if ( _schemaTable.Columns[counterCaseInSensitive].ColumnName.ToLower().Equals( name.ToLower() ) )
{
return counterCaseInSensitive;
}
}
throw new IndexOutOfRangeException( "Cannot find column " + name );
}
/// <summary>
/// Gets the data type information for the specified field. Currently Not Implemented
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The data type information for the specified field.</returns>
public string GetDataTypeName(int i)
{
this.NotImplemented("MockDataReader.GetDataTypeName");
return null;
}
/// <summary>
/// Gets the single-precision floating point number of the specified field.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The single-precision floating point number of the specified field.</returns>
public float GetFloat(int i)
{
return (float) GetValue(i);
}
/// <summary>
/// Gets an IDataReader to be used when the field points to more remote structured data.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>An IDataReader to be used when the field points to more remote structured data.</returns>
public System.Data.IDataReader GetData(int i)
{
return (IDataReader) GetValue(i);
}
/// <summary>
/// Reads a stream of characters from the specified column offset into the buffer as an array, starting at the given buffer offset.
/// </summary>
/// <param name="i">The zero-based column ordinal. </param>
/// <param name="fieldoffset">The index within the row from which to begin the read operation. </param>
/// <param name="buffer">The buffer into which to read the stream of bytes. </param>
/// <param name="bufferoffset">The index for buffer to begin the read operation. </param>
/// <param name="length">The number of bytes to read. </param>
/// <returns></returns>
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
{
this.NotImplemented("MockDataReader.GetChars");
return 0;
}
/// <summary>
/// Gets the string value of the specified field.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The string value of the specified field.</returns>
public string GetString(int i)
{
return Convert.ToString(GetValue(i));
}
/// <summary>
/// Gets the character value of the specified column.
/// </summary>
/// <param name="i">The zero-based column ordinal. </param>
/// <returns>The character value of the specified column.</returns>
public char GetChar(int i)
{
return Convert.ToChar(GetValue(i));
}
/// <summary>
/// Gets the 16-bit signed integer value of the specified field.
/// </summary>
/// <param name="i">The index of the field to find. </param>
/// <returns>The 16-bit signed integer value of the specified field.</returns>
public short GetInt16(int i)
{
return Convert.ToInt16(GetValue(i));
}
/// <summary>
/// Gets the specified column by name.
/// </summary>
public object this[string name]
{
get
{
return this[findColumnIndexForName(name)];
}
}
/// <summary>
/// Gets the specified column by index
/// </summary>
public object this[int i]
{
get
{
return GetValue(i);
}
}
/// <summary>
/// Gets the number of columns in the current row.
/// </summary>
public int FieldCount
{
get
{
if ( _schemaTable == null )
{
return -1;
}
return _schemaTable.Columns.Count;
}
}
#endregion
#endregion
#region Implementation of IDisposable
/// <summary>
/// <see cref="IDisposable.Dispose"/>
/// </summary>
public void Dispose()
{
if ( !IsClosed )
{
Close();
}
}
#endregion
#region Private Methods
/// <summary>
/// Finds the index of the given name
/// </summary>
/// <param name="name">Name of the column to find</param>
/// <returns>Column index of the given name</returns>
private int findColumnIndexForName(string name)
{
if (_schemaTable != null)
{
for (int i = 0; i < _schemaTable.Columns.Count; ++i)
{
if (_schemaTable.Columns[i].ColumnName.Equals(name))
{
return i;
}
}
}
throw new IndexOutOfRangeException("Column name: " + name + " not found");
}
/// <summary>
/// Helper method that determines if there are more rows to be read or not.
/// </summary>
/// <returns>true if there are more rows; false otherwise</returns>
private bool innerExecute()
{
if (_currentRow + 1 >= _rows.GetLength(0))
{
return false;
}
_currentRow++;
return true;
}
#endregion
}
}
|