views:

150

answers:

2

Please take a look at the following article about testing with mocks

So there is an example of unit test with mock objects. As you can see, the test is written for GetPersonByID method. In the IPersonServices interface there is another method: List<Person> GetPersons();

Can anyone tell me how a Test method on this service should look using mock objects? e.g., in the case of GetPersons, which has a List type.

+5  A: 

You'd be better off finding a different example of unit testing with Rhino.Mocks. The example there mocks the actual class under test, which you would never do.

Let's assume that you have a PersonRepository and a PersonService. You want to unit test the PersonService which uses the PersonRepository. Implementation of Person omitted.

 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();
     }
}

Now we have unit tests to ensure that the service is properly calling the repository.

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();
}
tvanfosson
Don't you need to put your mock repositories into replay mode after setting the expectations?
Don Kirkby
This is using the new AAA (Arrange Act Assert) syntax -- it doesn't require that you explicitly put them in replay mode.
tvanfosson
Nice. I haven't seen that syntax before, and I didn't notice that you were calling `Expect()` directly on the mock object. The wiki doesn't have much to say about the new syntax yet; next time I write some tests, I'll have to take a stab at contributing.
Don Kirkby
There is a description of the Arrange Act Assert syntax on the wiki, it just hasn't percolated down into the introduction and other examples. Here's the description of Rhino Mocks 3.5, including AAA syntax: http://www.ayende.com/wiki/Rhino+Mocks+3.5.ashx
Don Kirkby
@Don- nice link I was going to add it myself. It's a shame the other examples don't have this syntax it is much nicer.
RichardOD
A: 

As tvanfosson said, that's not a very useful example.

Here's an example from the 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();
        }

I don't think there's anything special about returning a List type from a mocked method call. Just set up the expectation as normal. In the example above, if the Ask() method returned a list of strings, the Return() method after Expect.Call(...Ask...) would take a list of strings. That's the lovely thing about the combination of record/replay mocking and generics, your expectations have type safety built in. Much nicer than earlier mock object libraries where you defined everything with method names in strings and all return values were just objects.

For more explanation of that example, along with many others, check out the Rhino Mocks wiki.

Don Kirkby
and how to set up the expectation as normal? can you give me an example?
qwerty