views:

238

answers:

3

i have just started using Moq ver (3.1) and i have read blogs and what not.... anyway... i guess until you makes your hand dirty you will not learn :)

okay here is what i'm testing...

  var newProduct = new Mock<IPartialPerson>();   
  newProduct.SetupGet(p => p.FirstName).Returns("FirstName");   
  newProduct.SetupGet(p => p.MiddleName).Returns("MiddleName");   
  newProduct.SetupGet(p => p.LastName).Returns("LastName");   
  newProduct.SetupGet(p => p.EmailAddress).Returns("[email protected]");   
  newProduct.SetupGet(p => p.UserID).Returns("UserID");   

  //mock Escort repository   
  var mockEscortRepository = new Mock<IEscortRepository>();     
  mockEscortRepository.Setup(p => p.LoadAllEscorts())   
      .Returns(newProduct.Object); //error  

Error 1 The best overloaded method match for 'Moq.Language.IReturns>.Returns(System.Collections.Generic.List)' has some invalid arguments


Error 2 Argument '1': cannot convert from 'App.Model.Interface.IPartialPerson' to 'System.Collections.Generic.List'


public interface IPartialPerson   
    {   
        string FirstName { get; }   
        string MiddleName { get; }   
        string LastName { get; }   
        string EmailAddress { get; }   
        string FullName { get; }   
        string UserID { get; }   

    }  

public interface IEscortRepository   
   {   
       List<PartialPerson> LoadAllEscorts();   
       List<PartialPerson> SelectedEscorts(List<PartialPerson> selectedEscorts);     
   }  

i have two methods that i want to test "LoadAllaEscorts" and "SelectedEscorts"

how would i do a test for both methods?

+5  A: 

Try this:

mockEscortRepository
.Setup(p => p.LoadAllEscorts())
.Returns(new List<IPartialPerson>() { newProduct.Object } ); 

When you say:

.Returns(newProduct.Object)

You are asking Moq to return one specific object. The compiler sees that your method returns a list and so it will not compile unless you provide a list for it to return. So you need to create a list that contains the object you want to return then ask Moq to return that instead.

Based on your comments you might also be interested in testing a list with more than one item. To do that, create a list with more than one item, then ask the Mock to return that. Here is one way you could create a list with more than one item:

List<PartialPerson> escorts = new List<PartialPerson>();
for (int i = 0; i < 10; i++)
{

    var escort = new Mock<IPartialPerson>();
    escort.SetupGet(p => p.FirstName).Returns("FirstName" + i);
    escort.SetupGet(p => p.MiddleName).Returns("MiddleName" + i);
    escort.SetupGet(p => p.LastName).Returns("LastName" + i);
    escort.SetupGet(p => p.EmailAddress).Returns(i + "[email protected]");
    escort.SetupGet(p => p.UserID).Returns("UserID" + i);
    escorts.Add(escort.Object);
}

mockEscortRepository
    .Setup(p => p.LoadAllEscorts())
    .Returns(escorts); 

Good luck and keep on pimpin!

magnifico
magnifico:is there a way i can test how many items it should return? from LoadAllaEscorts() ?and last, how would i test the List SelectedEscorts(List selectedEscorts);if my questions sounds you silly, please bare with me and i have just started learning...thanks for your reply.
Abu Hamzah
The mock will return whatever you put into it. So a test on what the mock "should" return is meaningless. You would have to write your test against a real repository to do that.
magnifico
ic what you mean.so the above will return one item? because i put one item?if i want to test more then one how would i do?
Abu Hamzah
getting errorsThe best overloaded method match for 'Moq.Language.IReturns<App.Repositories.Interface.IEscortRepository,Generic.List<App.Model.PartialPerson>>.Returns(Generic.List<App.Model.PartialPerson>)' has some invalid argumentscannot convert from 'Moq.Mock<App.Model.Interface.IPartialPerson>'to 'System.Collections.Generic.List<App.Model.PartialPerson>'
Abu Hamzah
the above sample does not work, anybody? please
Abu Hamzah
I made updates to the answer, but I think the compiler error is pretty clear about what was wrong with the code. Good luck with your escort website project, I won't be making any more updates to this answer.
magnifico
magnifico : thanks for your feedback, your updated code was throwing error... anyway i want to understand how would you use moq.thanks for your time.
Abu Hamzah
A: 

Your mock is setup to return a single item, and it should return a List according to the repository interface.

Luhmann
+2  A: 

i have two methods that i want to test "LoadAllaEscorts" and "SelectedEscorts"

Those are methods on an interface. You don't write tests against an interface, or against mock objects. You write tests against concrete classes.

Somewhere you have an EscortRepository that implements IEscortRepository. I'm assuming that hits the database. Write integration tests against that.

Elsewhere in your code you probably have a class (call it "Foo") that has an IEscortRepository dependency injected into it (such as via a constructor parameter). When you want to write tests against the Foo class, you would use Moq to create a mock IEscortRepository returning fixed test data and pass that mock object into your Foo instance.

Another issue is that your IEscortRepository methods are returning (or taking as a parameter) List<PartialPerson>. Those should be IList<IPartialPerson> (or IEnumerable<T>, ICollection<T>, or ReadOnlyCollection<T>). The most important part is that the collection items should be an interface type (IPartialPerson).

+1 for magnifico, who had the code right:

using System;
using System.Collections.Generic;
using Moq;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var newProduct = new Mock<IPartialPerson>();

            newProduct.SetupGet(p => p.FirstName).Returns("FirstName");
            newProduct.SetupGet(p => p.MiddleName).Returns("MiddleName");
            newProduct.SetupGet(p => p.LastName).Returns("LastName");
            newProduct.SetupGet(p => p.EmailAddress).Returns("[email protected]");
            newProduct.SetupGet(p => p.UserID).Returns("UserID");

            var mockEscortRepository = new Mock<IEscortRepository>();

            mockEscortRepository
                .Setup(p => p.LoadAllEscorts())
                .Returns(new List<IPartialPerson> {newProduct.Object});

            IEscortRepository repository = mockEscortRepository.Object;

            IList<IPartialPerson> escorts = repository.LoadAllEscorts();

            foreach (IPartialPerson person in escorts)
            {
                Console.WriteLine(person.FirstName + " " + person.LastName);
            }

            Console.ReadLine();

            // Outputs "FirstName LastName"
        }
    }

    public interface IPartialPerson
    {
        string FirstName { get; }
        string MiddleName { get; }
        string LastName { get; }
        string EmailAddress { get; }
        string FullName { get; }
        string UserID { get; }
    }

    public interface IEscortRepository
    {
        IList<IPartialPerson> LoadAllEscorts();
        IList<IPartialPerson> SelectedEscorts(IList<IPartialPerson> selectedEscorts);
    }
}

(The above example is not a unit test; it just shows that Moq works.)

Note that you don't have to use SetupGet for properties; Setup works as well.

TrueWill