Da Sie Linq to Sql verwenden, finden Sie hier ein Beispiel für das Testen des von Ihnen erwähnten Szenarios mit NUnit und Moq. Ich kenne nicht die genauen Details Ihres DataContext und was Sie darin zur Verfügung haben. Bearbeiten Sie es für Ihre Bedürfnisse.
Sie müssen den DataContext mit einer benutzerdefinierten Klasse umhüllen, Sie können den DataContext nicht mit Moq mocken. Sie können auch nicht SqlException nachbilden, da diese Klasse versiegelt ist. Sie müssen sie mit Ihrer eigenen Exception-Klasse umhüllen. Es ist nicht allzu schwierig, diese beiden Dinge zu erreichen.
Beginnen wir mit der Erstellung unseres Tests:
[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);
}
Implementieren wir den Test, verpacken wir zunächst unsere Linq to Sql-Aufrufe mit dem Repository-Muster:
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);
}
}
Als Nächstes erstellen Sie den IDataContextWrapper wie folgt, Sie können dies sehen Blogbeitrag zu diesem Thema, meine unterscheidet sich ein wenig:
public interface IDataContextWrapper : IDisposable
{
Table<T> Table<T>() where T : class;
}
Als nächstes erstellen Sie die Klasse CustomSqlException:
public class CustomSqlException : Exception
{
public CustomSqlException()
{
}
public CustomSqlException(string message, SqlException innerException) : base(message, innerException)
{
}
}
Hier ist eine Beispielimplementierung des 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
}