请查看以下article about testing with mocks
所以有一个使用模拟对象进行单元测试的例子。如您所见,测试是针对GetPersonByID
方法编写的。在IPersonServices
界面中还有另一种方法:List<Person> GetPersons()
;
有人能告诉我这个服务的Test方法应该如何使用模拟对象?例如,在GetPersons
的情况下,其具有List
类型。
答案 0 :(得分:5)
使用Rhino.Mocks查找不同的单元测试示例会更好。这个例子嘲笑了实际的测试类,你永远不会这样做。
假设您有PersonRepository和PersonService。您希望对使用PersonRepository的PersonService进行单元测试。省略了人的实施。
public interface IPersonService
{
Person GetPerson( int id );
List<Person> GetPersons();
}
public class PersonRepository
{
public virtual GetPerson( int id )
{
... implementation
}
public virtual GetPersons()
{
... implementation
}
}
public class PersonService : IPersonService
{
private PersonRepository Repository { get; set; }
public PersonService() : this(null) { }
public PersonService( PersonRepository repository )
{
this.Repository = repository ?? new PersonRepository();
}
public Person GetPerson( int id )
{
return this.Repository.GetPerson( id );
}
public List<Person> GetPersons()
{
return this.Repository.GetPersons();
}
}
现在我们进行了单元测试,以确保服务正确调用存储库。
public void GetPersonTest()
{
var repository = MockRepository.GenerateMock<PersonRepository>();
var expectedPerson = new Person( 1, "Name" );
repository.Expect( r => r.GetPerson( 1 ) ).Return( expectedPerson );
var service = new PersonService( repository );
var actualPerson = service.GetPerson( 1 );
Assert.AreEqual( expectedPerson.ID, actualPerson.ID );
Assert.AreEqual( expectedPerson.Name, actualPerson.Name );
repository.VerifyAllExpectations();
}
public void GetPersonsTest()
{
var repository = MockRepository.GenerateMock<PersonRepository>();
var expectedPerson = new Person( 1, "Name" );
var listOfPeople = new List<Person> { expectedPerson };
repository.Expect( r => r.GetPersons() ).Return( listOfPeople );
var service = new PersonService( repository );
var actualList = service.GetPersons( );
Assert.AreEqual( 1, actualList.Count );
var actualPerson = actualList.First();
Assert.AreEqual( expectedPerson.ID, actualPerson.ID );
Assert.AreEqual( expectedPerson.Name, actualPerson.Name );
repository.VerifyAllExpectations();
}
答案 1 :(得分:0)
作为tvanfosson said,这不是一个非常有用的例子。
以下是Rhino Mocks wiki的示例。
[Test]
public void SaveProjectAs_CanBeCanceled()
{
MockRepository mocks = new MockRepository();
// projectView is the mock object
IProjectView projectView = mocks.StrictMock<IProjectView>();
Project prj = new Project("Example Project");
// presenter is the object under test
IProjectPresenter presenter = new ProjectPresenter(prj, projectView);
// set expectations on the mock object
Expect.Call(projectView.Title).Return(prj.Name);
Expect.Call(projectView.Ask(question, answer)).Return(null);
mocks.ReplayAll();
// now execute the test
Assert.IsFalse(presenter.SaveProjectAs());
mocks.VerifyAll();
}
我认为从模拟方法调用返回List类型没有什么特别之处。只是设定正常的期望。在上面的示例中,如果Ask()
方法返回了字符串列表,Return()
之后的Expect.Call(...Ask...)
方法将获取字符串列表。这是关于记录/重放模拟和泛型组合的可爱之处,您的期望内置了类型安全性。比早期的模拟对象库更好,您可以在字符串中使用方法名称定义所有内容并返回所有返回值只是对象。
有关该示例的更多说明以及许多其他示例,请查看Rhino Mocks wiki。