由于您使用的是 Linq to Sql,因此这里是使用 NUnit 和 Moq 测试您提到的场景的示例。我不知道您的 DataContext 的确切细节以及您在其中可用的内容。根据您的需要进行编辑。
您将需要使用自定义类包装 DataContext,您不能使用 Moq 模拟 DataContext。您也不能模拟 SqlException,因为它是密封的。你需要用你自己的异常类来包装它。完成这两件事并不难。
让我们从创建我们的测试开始:
[Test]
public void FindBy_When_something_goes_wrong_Should_handle_the_CustomSqlException()
{
var mockDataContextWrapper = new Mock<IDataContextWrapper>();
mockDataContextWrapper.Setup(x => x.Table<User>()).Throws<CustomSqlException>();
IUserResository userRespoistory = new UserRepository(mockDataContextWrapper.Object);
// Now, because we have mocked everything and we are using dependency injection.
// When FindBy is called, instead of getting a user, we will get a CustomSqlException
// Now, inside of FindBy, wrap the call to the DataContextWrapper inside a try catch
// and handle the exception, then test that you handled it, like mocking a logger, then passing it into the repository and verifying that logMessage was called
User user = userRepository.FindBy(1);
}
让我们实现测试,首先让我们使用存储库模式包装我们的 Linq to Sql 调用:
public interface IUserRepository
{
User FindBy(int id);
}
public class UserRepository : IUserRepository
{
public IDataContextWrapper DataContextWrapper { get; protected set; }
public UserRepository(IDataContextWrapper dataContextWrapper)
{
DataContextWrapper = dataContextWrapper;
}
public User FindBy(int id)
{
return DataContextWrapper.Table<User>().SingleOrDefault(u => u.UserID == id);
}
}
接下来像这样创建 IDataContextWrapper,您可以查看有关该主题的这篇博文,我的有点不同:
public interface IDataContextWrapper : IDisposable
{
Table<T> Table<T>() where T : class;
}
接下来创建 CustomSqlException 类:
public class CustomSqlException : Exception
{
public CustomSqlException()
{
}
public CustomSqlException(string message, SqlException innerException) : base(message, innerException)
{
}
}
这是 IDataContextWrapper 的示例实现:
public class DataContextWrapper<T> : IDataContextWrapper where T : DataContext, new()
{
private readonly T _db;
public DataContextWrapper()
{
var t = typeof(T);
_db = (T)Activator.CreateInstance(t);
}
public DataContextWrapper(string connectionString)
{
var t = typeof(T);
_db = (T)Activator.CreateInstance(t, connectionString);
}
public Table<TableName> Table<TableName>() where TableName : class
{
try
{
return (Table<TableName>) _db.GetTable(typeof (TableName));
}
catch (SqlException exception)
{
// Wrap the SqlException with our custom one
throw new CustomSqlException("Ooops...", exception);
}
}
// IDispoable Members
}