views:

422

answers:

4

Hi all Beginner in Moq. Trying to understand the use of verifySet etc... but unless I do a workaround I cannot get it to work.

public interface IProduct
{
    int  Id { get; set; }
    string Name { get; set; }
}


public void Can_do_something()
{
    var newProduct = new Mock<IProduct>();
    newProduct.SetupGet(p => p.Id).Returns(1);
    newProduct.SetupGet(p => p.Name).Returns("Jo");

    //This fails!! why is it because I have not invoked it
    newProduct.VerifySet(p => p.Name, Times.AtLeastOnce());

    //if I do this it works
    newProduct.Object.Name = "Jo";
    newProduct.VerifySet(p => p.Name, Times.AtLeastOnce());
 }

Can somebody clarify how I should use VerifySet and Verify and VerifyGet on a property? I am getting confused.

Thanks a lot

+5  A: 

You need to perform an action before you call verify. The typical unit test paradigm with mock objects is:

// Arrange
// Act
// Assert

So the following is improper usage because you're missing your Act step:

public void Can_do_something()
{
    // Arrange
    var newProduct = new Mock<IProduct>();
    newProduct.SetupGet(p => p.Name).Returns("Jo");

    // Act - doesn't exist!
    // Your action against p.Name (ie method call), should occur here

    // Assert
    // This fails because p.Name has not had an action performed against it
    newProduct.VerifySet(p => p.Name, Times.AtLeastOnce());
}

And this is correct, since Act exists:

public void Can_do_something()
{
    // Arrange
    var newProduct = new Mock<IProduct>();
    newProduct.SetupGet(p => p.Name).Returns("Jo");

    // Act
    LoadProduct(newProduct.Object);

    // Assert
    newProduct.VerifySet(p => p.Name, Times.AtLeastOnce());
}

public static void LoadProduct(IProduct product)
{
    product.Name = "Jo";
}

Mock testing follows a different pattern than Non-Mock testing known as Behavior Verification - this is an answer I made that will clarify the concept a bit more.

Gavin Miller
+1  A: 

Arrange:

Instruct mock objects what is going to happen during the test. Tell it what events will fire, what methods and properties will be used, and what to do when these things happen.

Act:

Exercise the code under test.

Assert:

Ask the mock objects if what you told them to expect actually happened. Also inspect your code to see if it worked as you expected.

Your problem is that you Arranged and then Asserted without Acting inbetween. The Verify series of methods assert that what you said would happen in the Setup methods actually happened.

Will
+1  A: 

You are using VerifySet() in the correct manner, you've just omitted the //Act stage from the typical

//Arrange

//Act

//Assert

test construction. As you suggested, inserting

newProduct.Object.Name = "Jo";

into your //Act stage fixes the issue.

VerifyGet() would be used in the exact same manner, e.g.

//Arrange
var newProduct = new Mock<IProduct>();
newProduct.SetupGet(p => p.Id).Returns(1);
newProduct.SetupGet(p => p.Name).Returns("Jo");

//Act
string productName = newProduct.Object.Name;

//Assert
newProduct.VerifyGet(p => p.Name, Times.AtLeastOnce());

newProduct.Verify() is used to verify whatever action you specify, e.g.

//Arrange
var newProduct = new Mock<IProduct>();
newProduct.SetupGet(p => p.Id).Returns(1);
newProduct.SetupGet(p => p.Name).Returns("Jo");

//Act
newProduct.Object.SomeMethodYouDefineOnTheProductObject();

//Assert
newProduct.Verify(p => p.SomeMethodYouDefineOnTheProductObject(), Times.AtLeastOnce());
BenA
A: 

Thanks guys Unfortunately I am new to all this and trying to learn fast.Especially the terminology "act" "arrange" etc

So eventhough i didnt understand what I was doing I did it correctly as

newProduct.Object.Name = "Jo";

was setting up an act.

Fantastic explanation guys thanks a lot

One last thing though I thought these would "set up and act" but it's not the case correct is it? do you know the diff as well between the two SetupProperty and SetupSet/Get

mock.SetupProperty(f => f.Surname, "foo");

mock.SetupSet(foo => foo.Surname = "foo");