using System.Data; using NUnit.Framework; using NSubstitute; namespace YourNamespace.Tests { [TestFixture] public class DatabaseShould { private IDbConnection _connection; private IDbTransaction _transaction; private IDbCommand _command; [SetUp] public void Setup() { _connection = Substitute.For(); _transaction = Substitute.For(); _command = Substitute.For(); _connection.BeginTransaction().Returns(_transaction); _connection.CreateCommand().Returns(_command); } [Test] public void ExecuteQuery_ReturnExpectedResults() { var reader = Substitute.For(); reader.Read().Returns(true, true, false); reader[0].Returns("Value1", "Value2"); _command.ExecuteReader().Returns(reader); var sut = CreateSut(); var results = sut.ExecuteQuery("SELECT * FROM Table"); Assert.That(results.Count, Is.EqualTo(2)); Assert.That(results[0], Is.EqualTo("Value1")); Assert.That(results[1], Is.EqualTo("Value2")); } [Test] public void CommitTransaction_WhenOperationSucceeds() { var sut = CreateSut(); sut.ExecuteInTransaction(() => { _command.ExecuteNonQuery(); }); _transaction.Received(1).Commit(); } [Test] public void RollbackTransaction_WhenOperationFails() { _command.When(c => c.ExecuteNonQuery()).Do(_ => throw new System.Exception("DB Error")); var sut = CreateSut(); Assert.Throws(() => sut.ExecuteInTransaction(() => _command.ExecuteNonQuery())); _transaction.Received(1).Rollback(); } [Test] public void UseCorrectParameters_WhenExecutingCommand() { var parameter = Substitute.For(); _command.CreateParameter().Returns(parameter); var sut = CreateSut(); sut.ExecuteWithParameter("INSERT INTO Table (Col) VALUES (@val)", "@val", "TestValue"); _command.Received(1).Parameters.Add(Arg.Is(p => p.ParameterName == "@val" && (string)p.Value == "TestValue")); } [Test] public void ReturnRowCount_WhenExecutingNonQuery() { _command.ExecuteNonQuery().Returns(5); var sut = CreateSut(); var count = sut.ExecuteNonQuery("DELETE FROM Table"); Assert.That(count, Is.EqualTo(5)); } [Test] public void HandleNullValues_InQueryResults() { var reader = Substitute.For(); reader.Read().Returns(true, false); reader.IsDBNull(0).Returns(true); _command.ExecuteReader().Returns(reader); var sut = CreateSut(); var results = sut.ExecuteQuery("SELECT Col FROM Table"); Assert.That(results.Count, Is.EqualTo(1)); Assert.That(results[0], Is.Null); } [Test] public void CloseConnection_AfterOperation() { _connection.State.Returns(ConnectionState.Open); var sut = CreateSut(); sut.CloseConnection(); _connection.Received(1).Close(); } [Test] public void ThrowException_WhenConnectionFails() { _connection.When(c => c.Open()).Do(_ => throw new System.Exception("Connection failed")); var sut = CreateSut(); Assert.Throws(() => sut.OpenConnection()); } [Test] public void ExecuteScalar_ReturnCorrectValue() { _command.ExecuteScalar().Returns(42); var sut = CreateSut(); var result = sut.ExecuteScalar("SELECT COUNT(*) FROM Table"); Assert.That(result, Is.EqualTo(42)); } private DatabaseService CreateSut() { return new DatabaseService(_connection); } [TearDown] public void TearDown() { _connection?.Dispose(); _command?.Dispose(); } } public class DatabaseService { private readonly IDbConnection _connection; public DatabaseService(IDbConnection connection) { _connection = connection; } public void OpenConnection() => _connection.Open(); public void CloseConnection() { if (_connection.State == ConnectionState.Open) _connection.Close(); } public List ExecuteQuery(string sql) { var results = new List(); using (var command = _connection.CreateCommand()) { command.CommandText = sql; using (var reader = command.ExecuteReader()) { while (reader.Read()) { results.Add(reader.IsDBNull(0) ? null : reader[0]); } } } return results; } public int ExecuteNonQuery(string sql) { using (var command = _connection.CreateCommand()) { command.CommandText = sql; return command.ExecuteNonQuery(); } } public object ExecuteScalar(string sql) { using (var command = _connection.CreateCommand()) { command.CommandText = sql; return command.ExecuteScalar(); } } public void ExecuteInTransaction(Action operation) { using (var transaction = _connection.BeginTransaction()) { try { operation(); transaction.Commit(); } catch { transaction.Rollback(); throw; } } } public void ExecuteWithParameter(string sql, string paramName, object value) { using (var command = _connection.CreateCommand()) { command.CommandText = sql; var parameter = command.CreateParameter(); parameter.ParameterName = paramName; parameter.Value = value; command.Parameters.Add(parameter); command.ExecuteNonQuery(); } } } }