Search code examples
unit-testingpexintellitest

Testing changed reference parameters using Pex


Pex looks interesting from a characterisation testing perspective but I'm having trouble getting it to assert a change in an object passed by reference.

Given the code that I'm trying to test below:

public class ItemUpdater
{
    public void Update(Item item)
    {
        if (item.Name == "Two Times")
        {
            item.Quantity = item.Quantity*2;
        }
        if (item.Name == "Two more") {
            item.Quantity = item.Quantity + 2;
        }
    }
}

public class Item
{
    public string Name { get; set; }
    public int Quantity { get; set; }
}

What I'm looking to do is Create and Run intellitest tests against Update that will generate Characterisation/Locking tests so that I can make changes.

When tests are generated I get:

 [TestClass]
    [PexClass(typeof(ItemUpdater))]
    [PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentException), AcceptExceptionSubtypes = true)]
    [PexAllowedExceptionFromTypeUnderTest(typeof(InvalidOperationException))]
    public partial class ItemUpdaterTest
    {

        /// <summary>Test stub for Update(Item)</summary>
        [PexMethod]
        public void UpdateTest([PexAssumeUnderTest]ItemUpdater target, Item item) {
            PexAssume.IsNotNull(item);

            target.Update(item);

            var quality = item.Quantity;
            PexAssert.AreEqual(quality, item.Quantity);
            // TODO: add assertions to method ItemUpdaterTest.UpdateTest(ItemUpdater, Item)
        }
    }

I've added an assume to remove the null check tests, no problem here.

The problem I'm having is getting intellitest to auto-generate the item.Quantity assertions. I've also tried passing the quality as a parameter to UpdateTest(...., int quality) but this is always set to zero.

All that comes out is:

[TestMethod]
[PexGeneratedBy(typeof(ItemUpdaterTest))]
public void UpdateTest515()
{
    ItemUpdater s0 = new ItemUpdater();
    Item s1 = new Item();
    s1.Name = "Two more";
    s1.Quantity = 0;
    this.UpdateTest(s0, s1);
    Assert.IsNotNull((object)s0);
}

No asserting against the value of item.Quantity.

Does anyone know how to get Pex/Intellitest to generate assertions against the returned item.Quality after the Update method has been called?


Solution

  • I found out how to do this. The answer is to add PexObserve.ValueAtEndOfTest like so:

    [TestClass]
        [PexClass(typeof(ItemUpdater))]
        [PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentException), AcceptExceptionSubtypes = true)]
        [PexAllowedExceptionFromTypeUnderTest(typeof(InvalidOperationException))]
        public partial class ItemUpdaterTest
        {
    
            /// <summary>Test stub for Update(Item)</summary>
            [PexMethod]
            public void UpdateTest([PexAssumeUnderTest]ItemUpdater target, Item item) {
                PexAssume.IsNotNull(item);
    
                target.Update(item);
    
                var testable = item;
                PexObserve.ValueAtEndOfTest("Quantity", testable.Quantity);
            }
        }
    

    This will generate the code to test the parameters.