Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

verifying a list using moq

Given the calling code

List<Person> loginStaff = new List<Person>(); 

loginStaff.add(new Person{FirstName = "John", LastName = "Doe"});

this._iViewLoginPanel.Staff = loginStaff;

What is the syntax for verifying that there exists a staff by the name of john doe and that there is at least one staff being set? Currently, all the examples that I've seen are pretty basic, using only It.IsAny or Staff = some basic type but none actually verify data within complex types like lists.

My assert looks like

this._mockViewLoginPanel.VerifySet(x=> x.Staff = It.IsAny<List<Person>>());

which only checks the type given to the setter but not the size or items within the list itself. I've tried to do something like this:

        this._mockViewLoginPanel.VerifySet(
           x =>
           {
               List<string> expectedStaffs = new List<string>{"John Doe", "Joe Blow", "A A", "Blah"};
               foreach (Person staff in x.Staff)
               {
                   if (!expectedStaffs.Contains(staff.FirstName + " " + staff.LastName))
                       return false;
               }
               return true;
           });

But that tells me that the lambda statement body cannot be converted to an expression tree. Then i got the idea of putting the statement body into a function and running that, but during runtime I get:

System.ArgumentException: Expression is not a property setter invocation.

Update: In light of the first two answers to use assert, I tried that method but found that even after setting Staff to a non null list, it still shows up in debug as null. So this is how the full test looks

[TestMethod]
public void When_The_Presenter_Is_Created_Then_All_CP_Staff_Is_Added_To_Dropdown()
{
    this._mockViewLoginPanel = new Mock<IViewLoginPanel>();

    PresenterLoginPanel target = new PresenterLoginPanel(this._mockViewLoginPanel.Object);

    this._mockViewLoginPanel
        .VerifySet(x => x.Staff = It.IsAny<List<Person>>());

    Assert.AreEqual(5, this._mockViewLoginPanel.Object.Staff.Count);
}

And somewhere within the constructor of PresenterLoginPanel

public PresenterLoginPanel
{
    private IViewLoginPanel _iViewLoginPanel;

    public PresenterLoginPanel(IViewLoginPanel panel) 
    { 
        this._iViewLoginPanel = panel;
        SomeFunction();
    }

    SomeFunction() {
        List<Person> loginStaff = new List<Person>(); 

        loginStaff.add(new Person{FirstName = "John", LastName = "Doe"});

        this._iViewLoginPanel.Staff = loginStaff;
    }
}

When i debug to the next line, this._iViewLoginPanel.Staff is null which is what's causing the null exception in the assert.

like image 492
Joe Avatar asked Jan 19 '11 00:01

Joe


3 Answers

Rather than using the mock's methods, you can use NUnit methods to make assertions about the contents of the mock object.

Once you've assigned the list to the object and verified it has been set, use assertions to check specifics, such as the item count and that the first object matches what you expect it to contain.

Assert.That(this._mockViewLoginPanel.Object.Staff.Length, Is.EqualTo(1));
Assert.That(this._mockViewLoginPanel.Object.Staff[0], Is.Not.Null);
Assert.That(this._mockViewLoginPanel.Object.Staff[0], Is.EqualTo(loginStaff[0]));

Edit

After further investigation this comes down to Mock Behaviour. The properties Staff and Person weren't setup properly.

Do setup them up, alter your mock creation to this:

var _mockViewLoginPanel = new Mock<IViewLoginPanel>(MockBehavior.Strict);
_mockViewLoginPanel.SetupAllProperties();

A complete code listing of a demo is:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public interface IViewLoginPanel
{
    IList<Person> Staff { get; set; }
}

public class PresenterLoginPanel {

    private IViewLoginPanel _iViewLoginPanel;

    public PresenterLoginPanel(IViewLoginPanel panel) 
    { 
        _iViewLoginPanel = panel;
        SomeFunction();
    }

    public void SomeFunction() 
    {
        List<Person> loginStaff = new List<Person>(); 

        loginStaff.Add(new Person{FirstName = "John", LastName = "Doe"});

        _iViewLoginPanel.Staff = loginStaff;
    }

    public IViewLoginPanel ViewLoginPanel
    {
        get { return _iViewLoginPanel; }
    }
}

[TestFixture]
public class PresenterLoginPanelTests
{
    [Test]
    public void When_The_Presenter_Is_Created_Then_All_CP_Staff_Is_Added_To_Dropdown()
    {
        var _mockViewLoginPanel = new Mock<IViewLoginPanel>(MockBehavior.Strict);
        _mockViewLoginPanel.SetupAllProperties();

        PresenterLoginPanel target = new PresenterLoginPanel(_mockViewLoginPanel.Object);

        _mockViewLoginPanel.VerifySet(x => x.Staff = It.IsAny<List<Person>>());

        Assert.AreEqual(5, _mockViewLoginPanel.Object.Staff.Count);
    }

}
like image 170
Michael Shimmins Avatar answered Nov 16 '22 03:11

Michael Shimmins


You could easily accomplish this with Moq itself (also when you don't already have a reference to the expected result object) - just use the It.Is(..) method:

_mockViewLoginPanel.VerifySet(x => x.Staff = It.Is<List<Person>>(staff => staff.Count == 5));
_mockViewLoginPanel.VerifySet(x => x.Staff = It.Is<List<Person>>(staff => staff[0].FirstName == "John"));
like image 38
Carsten Hess Avatar answered Nov 16 '22 03:11

Carsten Hess


This checks that the staff count should be more than 0, that there should be at least one item that is not null and there is at least one item that has first name equal to Joe. if you want to compare the objects, you'll have to add a comparer.

Assert.AreNotEqual(this._mockViewLoginPanel.Object.Staff.Count, 0);
Assert.AreNotEqual(this._mockViewLoginPanel.Object.Staff.All(x => x == null), true);
Assert.AreEqual(this._mockViewLoginPanel.Object.Staff.Any(x => x.FirstName == "Joe"), true);
like image 1
Divi Avatar answered Nov 16 '22 02:11

Divi