Skip to content

Commit

Permalink
Merge pull request #35 from baztian/bugfix/ancient-date
Browse files Browse the repository at this point in the history
Don't fail on dates before 1900 on Python < 3
  • Loading branch information
baztian authored Mar 21, 2017
2 parents 0e482a2 + 2f0eaeb commit ef7ad4e
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 52 deletions.
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ Changelog
=========

- Next version - unreleased

- Don't fail on dates before 1900 on Python < 3.

- 1.1.0 - 2017-03-19

- Support BIT and TINYINT type mappings (thanks @Mokubyow for
Expand Down
8 changes: 6 additions & 2 deletions jaydebeapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,8 +595,12 @@ def _to_date(rs, col):
java_val = rs.getDate(col)
if not java_val:
return
d = datetime.datetime.strptime(str(java_val)[:10], "%Y-%m-%d")
return d.strftime("%Y-%m-%d")
# The following code requires Python 3.3+ on dates before year 1900.
# d = datetime.datetime.strptime(str(java_val)[:10], "%Y-%m-%d")
# return d.strftime("%Y-%m-%d")
# Workaround / simpler soltution (see
# https://github.com/baztian/jaydebeapi/issues/18):
return str(java_val)[:10]

def _to_binary(rs, col):
java_val = rs.getObject(col)
Expand Down
5 changes: 5 additions & 0 deletions mockdriver/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.mockito</groupId>
Expand Down
125 changes: 75 additions & 50 deletions mockdriver/src/main/java/org/jaydebeapi/mockdriver/MockConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,98 @@

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Calendar;
import org.mockito.Mockito;

public abstract class MockConnection implements Connection {

ResultSet mockResultSet;
ResultSet mockResultSet;

public final void mockExceptionOnCommit(String className, String exceptionMessage) throws SQLException {
Throwable exception = createException(className, exceptionMessage);
Mockito.doThrow(exception).when(this).commit();
private static Throwable createException(String className, String exceptionMessage) {
try {
return (Throwable) Class.forName(className).getConstructor(String.class)
.newInstance(exceptionMessage);
} catch (Exception e) {
throw new RuntimeException("Couldn't initialize class " + className + ".", e);
}
}

public final void mockExceptionOnRollback(String className, String exceptionMessage) throws SQLException {
Throwable exception = createException(className, exceptionMessage);
Mockito.doThrow(exception).when(this).rollback();
private static int extractTypeCodeForName(String sqlTypesName) {
try {
Field field = Types.class.getField(sqlTypesName);
return field.getInt(null);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException("Type " + sqlTypesName + " not found in Types class.", e);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

public final void mockExceptionOnExecute(String className, String exceptionMessage) throws SQLException {
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
Throwable exception = createException(className, exceptionMessage);
Mockito.when(mockPreparedStatement.execute()).thenThrow(exception);
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
}
public final void mockExceptionOnCommit(String className, String exceptionMessage)
throws SQLException {
Throwable exception = createException(className, exceptionMessage);
Mockito.doThrow(exception).when(this).commit();
}

public final void mockType(String sqlTypesName) throws SQLException {
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
Mockito.when(mockPreparedStatement.execute()).thenReturn(true);
mockResultSet = Mockito.mock(ResultSet.class, "ResultSet(for type " + sqlTypesName + ")");
Mockito.when(mockPreparedStatement.getResultSet()).thenReturn(mockResultSet);
Mockito.when(mockResultSet.next()).thenReturn(true);
ResultSetMetaData mockMetaData = Mockito.mock(ResultSetMetaData.class);
Mockito.when(mockResultSet.getMetaData()).thenReturn(mockMetaData);
Mockito.when(mockMetaData.getColumnCount()).thenReturn(1);
int sqlTypeCode = extractTypeCodeForName(sqlTypesName);
Mockito.when(mockMetaData.getColumnType(1)).thenReturn(sqlTypeCode);
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
}
public final void mockExceptionOnRollback(String className, String exceptionMessage)
throws SQLException {
Throwable exception = createException(className, exceptionMessage);
Mockito.doThrow(exception).when(this).rollback();
}

public final ResultSet verifyResultSet() {
return Mockito.verify(mockResultSet);
}
public final void mockExceptionOnExecute(String className, String exceptionMessage)
throws SQLException {
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
Throwable exception = createException(className, exceptionMessage);
Mockito.when(mockPreparedStatement.execute()).thenThrow(exception);
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
}

private static Throwable createException(String className, String exceptionMessage) {
try {
return (Throwable) Class.forName(className).getConstructor(String.class).newInstance(exceptionMessage);
} catch (Exception e) {
throw new RuntimeException("Couldn't initialize class " + className + ".", e);
}
}
public final void mockDateResult(int year, int month, int day) throws SQLException {
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
Mockito.when(mockPreparedStatement.execute()).thenReturn(true);
mockResultSet = Mockito.mock(ResultSet.class, "ResultSet(for date)");
Mockito.when(mockPreparedStatement.getResultSet()).thenReturn(mockResultSet);
Mockito.when(mockResultSet.next()).thenReturn(true);
ResultSetMetaData mockMetaData = Mockito.mock(ResultSetMetaData.class);
Mockito.when(mockResultSet.getMetaData()).thenReturn(mockMetaData);
Mockito.when(mockMetaData.getColumnCount()).thenReturn(1);
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1);
cal.set(Calendar.DAY_OF_MONTH, day);
Date ancientDate = new Date(cal.getTime().getTime());
Mockito.when(mockResultSet.getDate(1)).thenReturn(ancientDate);
Mockito.when(mockMetaData.getColumnType(1)).thenReturn(Types.DATE);
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
}

private static int extractTypeCodeForName(String sqlTypesName) {
try {
Field field = Types.class.getField(sqlTypesName);
return field.getInt(null);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException("Type " + sqlTypesName + " not found in Types class.", e);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public final void mockType(String sqlTypesName) throws SQLException {
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
Mockito.when(mockPreparedStatement.execute()).thenReturn(true);
mockResultSet = Mockito.mock(ResultSet.class, "ResultSet(for type " + sqlTypesName + ")");
Mockito.when(mockPreparedStatement.getResultSet()).thenReturn(mockResultSet);
Mockito.when(mockResultSet.next()).thenReturn(true);
ResultSetMetaData mockMetaData = Mockito.mock(ResultSetMetaData.class);
Mockito.when(mockResultSet.getMetaData()).thenReturn(mockMetaData);
Mockito.when(mockMetaData.getColumnCount()).thenReturn(1);
int sqlTypeCode = extractTypeCodeForName(sqlTypesName);
Mockito.when(mockMetaData.getColumnType(1)).thenReturn(sqlTypeCode);
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
}

public final ResultSet verifyResultSet() {
return Mockito.verify(mockResultSet);
}
}
7 changes: 7 additions & 0 deletions test/test_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ def test_all_db_api_type_objects_have_valid_mapping(self):
'getObject'))
verify_get(1)

def test_ancient_date_mapped(self):
self.conn.jconn.mockDateResult(1899, 12, 31)
cursor = self.conn.cursor()
cursor.execute("dummy stmt")
result = cursor.fetchone()
self.assertEquals(result[0], "1899-12-31")

def test_sql_exception_on_execute(self):
self.conn.jconn.mockExceptionOnExecute("java.sql.SQLException", "expected")
cursor = self.conn.cursor()
Expand Down

0 comments on commit ef7ad4e

Please sign in to comment.