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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s