Moq and throwing a SqlException

前端 未结 4 726
庸人自扰
庸人自扰 2020-12-25 11:25

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).<

4条回答
  •  一整个雨季
    2020-12-25 11:35

    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:

    using Moq;
    
    var sqlException = 
        new SqlExceptionBuilder().WithErrorNumber(50000)
            .WithErrorMessage("Database exception occured...")
            .Build();
    var repoStub = new Mock>(); // Or whatever...
    repoStub.Setup(stub => stub.GetById(1))
        .Throws(sqlException);
    

提交回复
热议问题