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.