In the application I've been working on, we have the requirement to handle unique constraint errors gracefully. It wasn't really hard, I just had to check for OracleException.Code == 1. The trick was the testing. Testing a unique constraint error was not a problem. The issue is verifying that other exceptions are bubbled up properly.
The basic exception handling code is like this:
1 protected bool HasUniqueConstraintError( Action databaseAction )
2 {
3 try
4 {
5 databaseAction();
6 return false;
7 }
8 catch( OracleException ex )
9 {
10 //Return true if exception is a Unique Constraint error
11 if( ex.Code == 1 )
12 return true;
13 else
14 throw;
15 }
16 }
Line 14 was not getting covered in my tests. Also, because I have the same requirement under various scenarios, I decided to move this logic to a shared library. The shared library doesn't deal with a real connection. (And using a real connection wouldn't be a true unit test anyway).
So, I tried to test by instantiating OracleException myself. Alas, OracleException has no public constructors nor any way to get a new instance. On top of that it is sealed, so I cannot create a subclass either. Then, I thought, maybe I can use serialization. I tried XmlSerializer, but it requires a public parameterless constructor.
Finally, I landed on SoapFormatter. Of course, I had to have a Soap message to start from. So, I did a little bit of work to reproduce a unique constraint exception in the debugger. I used SoapFormatter to serialize the OracleException and wrote it to a file. Then, I added the file to my test project (as an embedded resource). Finally, I wrote the test to use the embedded file and deserialze to an instance of OracleException I could throw. I did the same for another common Oracle error (ORA-12154: TNS). I verified that the unique constraint error was handled, while the TNS error was rethrown.
Here is the test code:
1 [Test]
2 public void TestHasUniqueConstraintError()
3 {
4 SoapFormatter formatter = new SoapFormatter();
5 Assembly asm = Assembly.GetExecutingAssembly();
6 using( Stream stream = asm.GetManifestResourceStream( "XCIS.Data.Nunit.OracleUniqueConstraintException.txt" ) )
7 {
8 OracleException testException = (OracleException)formatter.Deserialize( stream );
9 Assert.That( HasUniqueConstraintError( () => { throw testException; } ) );
10 }
11 }
12
13 [Test, ExpectedException( ExceptionType = typeof( OracleException ) )]
14 public void TestHasSomeOtherOracleError()
15 {
16 SoapFormatter formatter = new SoapFormatter();
17 Assembly asm = Assembly.GetExecutingAssembly();
18 using( Stream stream = asm.GetManifestResourceStream( "XCIS.Data.Nunit.OracleTNSException.txt" ) )
19 {
20 OracleException testException = (OracleException)formatter.Deserialize( stream );
21 HasUniqueConstraintError( () => { throw testException; } );
22 }
23 }