tags:

views:

715

answers:

4

Consider this class:

public class Cotent
{
   public virtual bool IsCheckedOut {get; private set;}
   public virtual void CheckOut()
   {
      IsCheckedOut = true;
   }

   public virtual void CheckIn()
   {
      //Do Nothing for now as demonstrating false positive test.
   }
}

The Checkin method is intentionally empty. Now i have a few test methods to verify the status of calling each method.

[TestMethod]
public void CheckOutSetsCheckedOutStatusToTrue()
{
    Content c = new Content();    
    c.CheckOut();
    Assert.AreEqual(true, c.IsCheckedOut); //Test works as expected
}

[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
    Content c = new Content();
    c.CheckIn();
    Assert.AreEqual(false, c.IsCheckedOut); //Test does not work as expected
}

The 2nd test passes for the wrong reasons. So how can i use mocking (moq) to verify that CheckIn is setting the IsCheckedOut property?

Thanks

EDIT

To clarify: I have a method called CheckIn() whose job it is to set the IsCheckedOut status to false.

You will see in my test code above that the Test will return false even if i do not set the property value to false; This is expected, nothing wrong here.

I think my question specifically is How can i verify that the CheckIn() method has set the IsCheckedOut property to false? This is what i would call behavioural verification.

I believe some of the comments suggested doing something which amounts to State verification? If so i dont believe there is any value in mocking this part at all when we can simply use:

Content c = new Content();    
c.CheckIn();    
Assert.AreEqual(false, c.IsCheckedOut); //State verification

Of course i may be wrong, so please help me clarify these concepts :)

A: 

The following should work. Configure your mock object as:

var mock=new Mock<IContent>();
mock.SetupSet(content => content.IsCheckedOut=It.IsAny<bool>()).Verifiable();

And after the test code:

mock.VerifySet(content => content.IsCheckedOut=It.IsAny<bool>());

I haven't tested it anyway, so please tell me if it works for you.

EDIT. Indeed, this will not work since the setter for IsCheckedOut is false.

Anyway, now I see that you never set the value of IsCheckedOut at class construction time. It would be a good idea to add the following to the Content class:

public Content()
{
    IsCheckedOut=false;
}
Konamiman
To clarify. I dont want to test the setter on the IsCheckedOut property, instead i want to test that the method CheckIn() has set IsCheckedOut = false; Also, IsCheckedOut property is private, so i dont think the setup will work. Is it even possible with what i want to do? Any more ideas?
IsCheckedOut is in your interface, so it can't be private?
FinnNk
FinnNk: only the getter is in the interface, the setter is private.
Konamiman
I'm testing using the implementation class - Content.
oops, yes sorry missed the private modifier when I read the question.
FinnNk
A: 

Can I suggest that you might be thinking about this in the wrong way - generally you should be setting something up, performing an action and then checking the behaviour (result). In this case does it really matter that it wasn't set to false by the setter - what should matter is that it is false in after a given scenario has been exercised. If you take tests in isolation this might seem a bit odd, but for anything your tests will exist in sets.

The situation would be different if you were testing the interaction between two classes - then it would be fine to set up an expectation on the property setter - as the setting action is the interaction you're testing.

I'm not familiar with Moq as I use Rhino.Mocks - but I'm guessing there'll be something along the lines of mock.VerifySet(content => content.IsCheckedOut=It.IsEqual(true));

FinnNk
Please see my edited post :)
+1  A: 

why don't you simply set up the content to be checked out to start with? Remember, you are only testing the behaviour of the CheckIn function.

[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
    // arrange - create a checked out item
    Content c = new Content();
    c.CheckOut();

    // act - check it in
    c.CheckIn();

    // assert - IsCheckedOut should be set back to false
    Assert.AreEqual(false, c.IsCheckedOut);
}
Mark Heath
I agree that the use of a mock(ing framework) does not feel necesary in this case. This suggested method is better since it tests the public interface rather than internal details (i.e. how the property is set).
Cellfish
A: 
Mock mockContect = new Mock<Cotent>(); 
mockContent.VerifySet(x => x.IsCheckedOut, Times.Once());

Will that do the trick? Not sure how the private setter comes in to play as havent tested that. but works for my public setter.

Got this from: http://www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-2.aspx

Dominic