Pseudorandom Knowledge

Testing the model

The model part of ASP.NET MVC is best tested in conjunction with the database.

public class ShipRepository : IShipRepository
{
    private string ConnectionString;
 
    public ShipRepository()
    {
        ConnectionString = ConfigurationManager
            .ConnectionStrings["Database"].ToString();
    }
 
    public ShipRepository(string connectionString)
    {
        ConnectionString = connectionString;
    }
 
    public IEnumerable<Ship> GetList()
    {
        const string query = "SELECT Name FROM Ships";
        var ships = new List<Ship>();
        using (var connection = new SqlConnection(ConnectionString))
        {
            connection.Open();
            using (var command = new SqlCommand(query, connection))
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    ships.Add(new Ship { Name = reader.GetString(0) });
                }
            }
        }
        return ships;
    }
 
    public void Insert(Ship ship)
    {
        var ships = new List<Ship>();
        using (var connection = new SqlConnection(ConnectionString))
        {
            connection.Open();
            using (var command = new SqlCommand("spInsertShip", connection))
            {
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.AddWithValue("@Name", ship.Name);
                command.ExecuteNonQuery();
            }
        }
    }
}

This class uses the repository pattern to manage the model.

[TestClass]
public class ShipRepositoryTests
{
    [TestCleanup]
    public void Cleanup()
    {
        RunNonQuery("TRUNCATE TABLE Ships");
    }
 
    [TestMethod]
    public void GetListReturnsAllRows()
    {
        // Arrange
        RunNonQuery("INSERT INTO Ships (Name) VALUES ('Ship 1')");
        RunNonQuery("INSERT INTO Ships (Name) VALUES ('Ship 2')");
        var repository = new ShipRepository(GetConnectionString());
 
        // Act
        IEnumerable<Ship> ships = repository.GetList();
 
        // Assert
        Assert.AreEqual(2, ships.Count());
        Assert.IsTrue(ships.Select(s => s.Name).Contains("Ship 1"));
        Assert.IsTrue(ships.Select(s => s.Name).Contains("Ship 2"));
    }
 
    [TestMethod]
    public void InsertShipInsertsRow()
    {
        // Arrange
        var repository = new ShipRepository(GetConnectionString());
 
        // Act
        repository.Insert(new Ship { Name = "New Ship" });
 
        // Assert
        var shipNames = RunStringListQuery("SELECT Name FROM Ships");
        Assert.AreEqual(1, shipNames.Count());
        Assert.IsTrue(shipNames.Contains("New Ship"));
    }
 
    private string GetConnectionString()
    {
        return ConfigurationManager
            .ConnectionStrings["Test"].ToString();
    }
 
    private void RunNonQuery(string query)
    {
        using (var connection = new SqlConnection(GetConnectionString()))
        {
            connection.Open();
            using (var command = new SqlCommand(query, connection))
            {
                command.ExecuteNonQuery();
            }
        }
    }
 
    private IEnumerable<string> RunStringListQuery(string query)
    {
        var result = new List<string>();
        using (var connection = new SqlConnection(GetConnectionString()))
        {
            connection.Open();
            using (var command = new SqlCommand(query, connection))
            using(var reader = command.ExecuteReader())
            {
                while(reader.Read())
                {
                    result.Add(reader.GetString(0));
                }
            }
        }
        return result;
    }
}

These tests are run against a separate test database which is emptied after each test.