A common data pattern in most business applications is the Repository pattern. An interface for a generic repository usually looks like the following:
public interface IRepository<T> where T : DomainEntity
{
IList<T> GetAll();
T GetById(int id);
void Commit(T entity);
void Delete(T entity);
}
public abstract class DomainEntity
{
public int? Id { get; set; }
public bool IsNew
{
get { return Id != null; }
}
}
Typically your service layer would co-ordinate entities and the repository to perform the required functionality. Logic concerning insertion of entities needs to test if the entity has been successfully insert by checking the IsNew property. The test for which could look like
public class Person : DomainEntity
{
public string Name { get; set; }
public Date DateOfBirth { get; set; }
}
public class IPersonRepository : IRepository<Person>
{
}
public class PersonService
{
private IPersoneRepository _repository;
public PersonService(IPersonRepository repository)
{
_repository = repository
}
public bool InsertPerson(string name, DateOfBirth dateOfBirth)
{
var newPerson = new Person
{
Name = name,
DateOfBirth = dateOfBirth
};
_repository.Commit(newPerson)
return !newPerson.IsNew;
}
}
[Test]
public void Repository_insert_sets_id_field()
{
// Arrange
IPersonRepository repo = MockRepository.GenerateStub<IPersonRepository>();
PersonSerivce service = new PersonService(repo);
// Act
bool result = service.InsertPerson("Test Pilot", DateTime.Now.AddYears(-30));
// Assert
Assert.IsTrue(result);
}
This test will fail though because the mock repository will not create and assign a Id primary key. We need to simulate the creation of the primary key in the commit to ensure the IsNew property on the entity returns false. This is done using the Callback method on the mock.
[Test]
public void Repository_insert_sets_id_field()
{
// Arrange
IPersonRepository repo = MockRepository.GenerateStub<IPersonRepository>();
PersonSerivce service = new PersonService(repo);
repo.Expect(r => r.Commit(Arg<Person>.Is.NotNull)
.Callback(new Delegate.Function<bool, Person>(
person => {
person.Id = 1;
return true;
}
));
// Act
bool result = service.InsertPerson("Test Pilot", DateTime.Now.AddYears(-30));
// Assert
Assert.IsTrue(result);
}