I have the following code to test that when a certain name is passed to my method, it throws a SQL exception (there is reason to that one, although it sounds a little odd).
mockAccountDAL.Setup(m => m.CreateAccount(It.IsAny<string>(), "Display Name 2", It.IsAny<string>())).Throws<SqlException>();
However, this won't compile because SqlException's constructor is internal:
'System.Data.SqlClient.SqlException' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TException' in the generic type or method 'Moq.Language.IThrows.Throws()'
Now, I could change this to state that it should throw Exception
, but that wouldn't work for me, because my method should return one status code if it is a SqlException
and another if it is any other exception. That's what my unit test is testing.
Is there any way to achieve this without either changing the logic of the method I'm testing, or not testing this scenario?
Unit testing is a powerful way to ensure that your code works as intended. It's a great way to combat the common “works on my machine” problem. Using Moq, you can mock out dependencies and make sure that you are testing the code in isolation.
If you must have your own message, you can create your own exception class, then assign the SqlException to the InnerException property. Or throw one of the other exceptions and do the same thing (the assign part).
An exception that provides information on a database access error or other errors. Each SQLException provides several kinds of information: a string describing the error. This is used as the Java Exception message, available via the method getMesasge .
If you need test cases for the Number
or Message
properties of the exception, you could use a builder (which uses reflection) like this:
using System; using System.Data.SqlClient; using System.Linq; using System.Reflection; public class SqlExceptionBuilder { private int errorNumber; private string errorMessage; public SqlException Build() { SqlError error = this.CreateError(); SqlErrorCollection errorCollection = this.CreateErrorCollection(error); SqlException exception = this.CreateException(errorCollection); return exception; } public SqlExceptionBuilder WithErrorNumber(int number) { this.errorNumber = number; return this; } public SqlExceptionBuilder WithErrorMessage(string message) { this.errorMessage = message; return this; } private SqlError CreateError() { // Create instance via reflection... var ctors = typeof(SqlError).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance); var firstSqlErrorCtor = ctors.FirstOrDefault( ctor => ctor.GetParameters().Count() == 7); // Need a specific constructor! SqlError error = firstSqlErrorCtor.Invoke( new object[] { this.errorNumber, new byte(), new byte(), string.Empty, string.Empty, string.Empty, new int() }) as SqlError; return error; } private SqlErrorCollection CreateErrorCollection(SqlError error) { // Create instance via reflection... var sqlErrorCollectionCtor = typeof(SqlErrorCollection).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0]; SqlErrorCollection errorCollection = sqlErrorCollectionCtor.Invoke(new object[] { }) as SqlErrorCollection; // Add error... typeof(SqlErrorCollection).GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(errorCollection, new object[] { error }); return errorCollection; } private SqlException CreateException(SqlErrorCollection errorCollection) { // Create instance via reflection... var ctor = typeof(SqlException).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0]; SqlException sqlException = ctor.Invoke( new object[] { // With message and error collection... this.errorMessage, errorCollection, null, Guid.NewGuid() }) as SqlException; return sqlException; } }
Then you could have a repository mock (for instance) throw an exception like this (this example uses the Moq
library):
using Moq; var sqlException = new SqlExceptionBuilder().WithErrorNumber(50000) .WithErrorMessage("Database exception occured...") .Build(); var repoStub = new Mock<IRepository<Product>>(); // Or whatever... repoStub.Setup(stub => stub.GetById(1)) .Throws(sqlException);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With