起订量和投掷的SQLException起订量、SQLException

2023-09-03 05:56:13 作者:我向来孤僻成性却念你好深

我有以下的code测试,当一个特定的名称传递给我的方法,它抛出一个SQL例外(有理由那一个,虽然听起来有些奇怪)。

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>();

不过,这并不能编译,因为SQLEXCEPTION的构造函数是内部的:

However, this won't compile because SqlException's constructor is internal:

System.Data.SqlClient.SqlException'必须是一个非抽象类型与   为了一个公共的无参数的构造函数使用它作为参数   在泛型类型或方法TException   Moq.Language.IThrows.Throws()

'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()'

现在,我可以改变这个声明,就应该抛出异常,但这不适合我,因为我的方法应该返回一个状态code如果是 SQLEXCEPTION ,另外如果是任何其他异常。这就是我的单元测试是测试。

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?

推荐答案

这应该工作:

using System.Runtime.Serialization;

var exception = FormatterServices.GetUninitializedObject(typeof(SqlException)) 
                as SqlException;

mockAccountDAL.Setup(m => m.CreateAccount(It.IsAny<string>(), "Display Name 2", 
                     It.IsAny<string>())).Throws(exception);

然而,使用 GetUninitializedObject 有这样的警告:

由于该对象的新实例被初始化为零,并没有   构造函数运行,对象可能不会再present的状态是   由该对象认为是有效的。

Because the new instance of the object is initialized to zero and no constructors are run, the object might not represent a state that is regarded as valid by that object.

如果这会导致什么问题,你也许可以使用一些更复杂的反射魔法创造,但这种方式可能是最简单(如果它工作)。

If this causes any problems, you can probably create it using some more involved reflection magic but this way is probably the simplest (if it works).