by Jim Cooper
codesimply.blogspot.com
A good unit test
- Atomic
- Deterministic (it should pass or fail)
- Repeatable
- Order Independent & Isolated
- Fast
- Easy to setup
var mockStudentRepository = MockRepository.GenerateMock<IStudentRepository>();
var student = new Student() { ... };
studentService.RegisterNewStudent(student);
mockStudentRepository.AssertWasCalled(x => x.Save(student));
//using mocks to verify property setters
var mockStudentView = MockRepository.GenerateMock<IStudentView>();
mockstudentView.AssertWasCalled(x => x.WasStudentSaved = true);
//using stubs to control the program flow
var mockStudentValidator = MockRepository.GenerateMock<IStudentValidator>();
mockStudentValidator.Stub(x => x.ValidateStudent(Arg<Student>.Is.Anything)).Return(true);
mockStudentView.Stub(x => x.ShouldSaveStudent).Return(true);
//do not use GenerateStub cause it will not work for read-only properties
var mockStudentView = MockRepository.GenerateStub<IStudentView>();
mockstudentView.ShouldSaveStudent = true;
- It's much easier to always use GenerateMock, you might need it anyway
- Actualy generatemock actually is a generatetestdouble
- Use Arrange,Act,Assert instead of Record,Replay (legacy: Record, Playback, Expect.Call, ReplayAll, VerifyAll, DynamicMocks vs StrictMocks)
//constraints
Arg<Student>.Is.Anything,NotNull,Same,...
Arg<Student>.Matches(y => y.Id == expectedStudentId && y.FirstName == expectedFirstName)
Arg<Student>.Matches(y => IsCustomerMatching(student, expectedStudentId, expectedFirstName)
Arg<List<Student>>.List.ContainsAll(new List<Student> {student1, student2, student3})
Arg<List<Student>>.List.Count(Rhino.Mocks.Constraints.Is.Equal(3))
Arg<List<Student>>.List.IsIn(student1)
Text.Contains("one"),EndsWidth,StartWith,Like,...
//example custom constraint
mockStudentRepository.AssertWasCalled(x => x.Save(Arg<Student>.Matches(new StudentConstraint(expectedStudent))));
public class StudentConstraint : AbstractConstraint
{
public StudentContraint(Student expectedStudent) {}
public override bool Eval(object actual) {}
public override string Message { get; set; } //called if eval is false
}
Avoid using out & ref parameters
out Arg<Student>.Out(new Student()).Dummy
ref Arg<Student>.Ref(Rhino.Mocks.Constraints.Is.Anything, new Student()).Dummy