Implement further exception handling improvements.

master
baztian 2015-04-10 08:22:03 +02:00
parent a2ba0fb2b1
commit 4ededf479d
4 changed files with 90 additions and 29 deletions

View File

@ -173,6 +173,9 @@ Changelog
- Enrich exceptions with message from java SQLExceptions - Enrich exceptions with message from java SQLExceptions
- Be more specific about DB API exceptions: Distinguish DatabaseError and
InterfaceError.
- Fix typo LONGNARCHAR vs LONGVARCHAR (thanks @datdo for reporting #4) - Fix typo LONGNARCHAR vs LONGVARCHAR (thanks @datdo for reporting #4)
- 0.1.5 - 2015-03-02 - 0.1.5 - 2015-03-02

View File

@ -13,9 +13,20 @@ public abstract class MockConnection implements Connection {
ResultSet mockResultSet; ResultSet mockResultSet;
public final void mockExceptionOnExecute(String exceptionMessage) throws SQLException { public final void mockExceptionOnCommit(String className, String exceptionMessage) throws SQLException {
Throwable exception = createException(className, exceptionMessage);
Mockito.doThrow(exception).when(this).commit();
}
public final void mockExceptionOnRollback(String className, String exceptionMessage) throws SQLException {
Throwable exception = createException(className, exceptionMessage);
Mockito.doThrow(exception).when(this).rollback();
}
public final void mockExceptionOnExecute(String className, String exceptionMessage) throws SQLException {
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class); PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
Mockito.when(mockPreparedStatement.execute()).thenThrow(new SQLException(exceptionMessage)); Throwable exception = createException(className, exceptionMessage);
Mockito.when(mockPreparedStatement.execute()).thenThrow(exception);
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement); Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
} }
@ -33,7 +44,19 @@ public abstract class MockConnection implements Connection {
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement); Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
} }
private int extractTypeCodeForName(String sqlTypesName) { public final ResultSet verifyResultSet() {
return Mockito.verify(mockResultSet);
}
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);
}
}
private static int extractTypeCodeForName(String sqlTypesName) {
try { try {
Field field = Types.class.getField(sqlTypesName); Field field = Types.class.getField(sqlTypesName);
return field.getInt(null); return field.getInt(null);
@ -48,8 +71,4 @@ public abstract class MockConnection implements Connection {
} }
} }
public final ResultSet verifyResultSet() {
return Mockito.verify(mockResultSet);
}
} }

View File

@ -41,13 +41,14 @@ _java_array_byte = None
_handle_sql_exception = None _handle_sql_exception = None
def _handle_sql_exception_jython(ex): def _handle_sql_exception_jython():
from java.sql import SQLException from java.sql import SQLException
if isinstance(ex, SQLException): exc_info = sys.exc_info()
# TODO get stacktrace if isinstance(exc_info[1], SQLException):
raise Error, ex.getMessage() exc_type = DatabaseError
else: else:
raise ex exc_type = InterfaceError
raise exc_type, exc_info[1], exc_info[2]
def _jdbc_connect_jython(jclassname, jars, libs, *args): def _jdbc_connect_jython(jclassname, jars, libs, *args):
if _jdbc_name_to_const is None: if _jdbc_name_to_const is None:
@ -103,14 +104,15 @@ def _prepare_jython():
global _handle_sql_exception global _handle_sql_exception
_handle_sql_exception = _handle_sql_exception_jython _handle_sql_exception = _handle_sql_exception_jython
def _handle_sql_exception_jpype(ex): def _handle_sql_exception_jpype():
import jpype import jpype
SQLException = jpype.java.sql.SQLException SQLException = jpype.java.sql.SQLException
if issubclass(ex.__javaclass__, SQLException): exc_info = sys.exc_info()
# TODO get stacktrace if issubclass(exc_info[1].__javaclass__, SQLException):
raise Error, ex.message() exc_type = DatabaseError
else: else:
raise ex exc_type = InterfaceError
raise exc_type, exc_info[1], exc_info[2]
def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args): def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args):
import jpype import jpype
@ -353,15 +355,13 @@ class Connection(object):
try: try:
self.jconn.commit() self.jconn.commit()
except: except:
ex = sys.exc_info()[1] _handle_sql_exception()
_handle_sql_exception(ex)
def rollback(self): def rollback(self):
try: try:
self.jconn.rollback() self.jconn.rollback()
except: except:
ex = sys.exc_info()[1] _handle_sql_exception()
_handle_sql_exception(ex)
def cursor(self): def cursor(self):
return Cursor(self, self._converters) return Cursor(self, self._converters)
@ -445,8 +445,7 @@ class Cursor(object):
try: try:
is_rs = self._prep.execute() is_rs = self._prep.execute()
except: except:
ex = sys.exc_info()[1] _handle_sql_exception()
_handle_sql_exception(ex)
if is_rs: if is_rs:
self._rs = self._prep.getResultSet() self._rs = self._prep.getResultSet()
self._meta = self._rs.getMetaData() self._meta = self._rs.getMetaData()
@ -454,7 +453,7 @@ class Cursor(object):
else: else:
self.rowcount = self._prep.getUpdateCount() self.rowcount = self._prep.getUpdateCount()
# self._prep.getWarnings() ??? # self._prep.getWarnings() ???
def executemany(self, operation, seq_of_parameters): def executemany(self, operation, seq_of_parameters):
self._close_last() self._close_last()
self._prep = self._connection.jconn.prepareStatement(operation) self._prep = self._connection.jconn.prepareStatement(operation)

View File

@ -47,12 +47,52 @@ class MockTest(unittest.TestCase):
'getObject')) 'getObject'))
verify_get(1) verify_get(1)
def test_exception_on_execute(self): def test_sql_exception_on_execute(self):
dummy_msg = "expected" self.conn.jconn.mockExceptionOnExecute("java.sql.SQLException", "expected")
self.conn.jconn.mockExceptionOnExecute(dummy_msg)
cursor = self.conn.cursor() cursor = self.conn.cursor()
try: try:
cursor.execute("dummy stmt") cursor.execute("dummy stmt")
fail("expected exception") fail("expected exception")
except jaydebeapi.Error, e: except jaydebeapi.DatabaseError, e:
self.assertEquals(str(e), 'expected') self.assertEquals(str(e), "java.sql.SQLException: expected")
def test_runtime_exception_on_execute(self):
self.conn.jconn.mockExceptionOnExecute("java.lang.RuntimeException", "expected")
cursor = self.conn.cursor()
try:
cursor.execute("dummy stmt")
fail("expected exception")
except jaydebeapi.InterfaceError, e:
self.assertEquals(str(e), "java.lang.RuntimeException: expected")
def test_sql_exception_on_commit(self):
self.conn.jconn.mockExceptionOnCommit("java.sql.SQLException", "expected")
try:
self.conn.commit()
fail("expected exception")
except jaydebeapi.DatabaseError, e:
self.assertEquals(str(e), "java.sql.SQLException: expected")
def test_runtime_exception_on_commit(self):
self.conn.jconn.mockExceptionOnCommit("java.lang.RuntimeException", "expected")
try:
self.conn.commit()
fail("expected exception")
except jaydebeapi.InterfaceError, e:
self.assertEquals(str(e), "java.lang.RuntimeException: expected")
def test_sql_exception_on_rollback(self):
self.conn.jconn.mockExceptionOnRollback("java.sql.SQLException", "expected")
try:
self.conn.rollback()
fail("expected exception")
except jaydebeapi.DatabaseError, e:
self.assertEquals(str(e), "java.sql.SQLException: expected")
def test_runtime_exception_on_rollback(self):
self.conn.jconn.mockExceptionOnRollback("java.lang.RuntimeException", "expected")
try:
self.conn.rollback()
fail("expected exception")
except jaydebeapi.InterfaceError, e:
self.assertEquals(str(e), "java.lang.RuntimeException: expected")