Mock objects not always being used

3 posts, 0 answers
  1. Peter
    Peter avatar
    2 posts
    Member since:
    Sep 2013

    Posted 07 Sep 2013 Link to this post

    I'm trying to test the following, and the class under test's internals are visible to the test class:

    public class PriceSeries
    {
        private double _avPrice = 650;
        private double _relativePriceVol = 0.025;
        private double _priceRegress = 0.2;
        private double _currPrice = 650;
     
        private readonly Random _oracle = new Random();
     
        public double AvPrice
        {
            get { return _avPrice; }
            private set { if(value > 0) {_avPrice = value;} }
        }
     
        public double CurrPrice
        {
            get { return _currPrice; }
            private set { if (value > 0) { _currPrice = value; } }
        }
     
        public double RelativePriceVol
        {
            get { return _relativePriceVol; }
            private set { if(value > 0 && value < 1) { _relativePriceVol = value; } }
        }
     
        public double PriceRegress
        {
            get { return _priceRegress; }
            private set { if (value > 0 && value < 1) { _priceRegress = value; } }
        }
     
        /// <summary>
        /// Return NdX
        /// </summary>
        /// <param name="numdice">Number of dice being rolled</param>
        /// <param name="numfaces">Highest numbered face on die</param>
        /// <returns></returns>
        internal int[] RollDice(int numdice, int numfaces)
        {
            numdice = Math.Max(1, numdice);
            numfaces = Math.Max(1, numfaces);
            int[] dice = new int[numdice];
            for(int i=0;i<numdice;i++)
            { dice[i] = RollOneDie(numfaces); }
            return dice;
        }
     
        public double GetNextPrice()
        {
            int[] dice = RollDice(4, 6);
            int sum = -14;
            foreach(int t in dice)
            { sum += t; }
            double result = this.CurrPrice + this.PriceRegress*(this.AvPrice - this.CurrPrice)
     +
    this.AvPrice*this.RelativePriceVol*sum;
            return result;
        }
     
        internal int RollOneDie(int numfaces)
        {
            return _oracle.Next(numfaces) + 1;
        }
    }


    With these unit tests

    [TestMethod]
    public void TestFirstPriceGen()
    {
        PriceSeries target = new PriceSeries();
        // mock out dice roll
        int[] mockroll = new int[] {3,5,4,5};
        Mock.Arrange(() => target.RollDice(4, 6)).Returns(mockroll);
         
        double expectedPrice = 698.75;  // dice roll of +3 from initialisation
     
        double actualPrice = target.GetNextPrice();
        Assert.AreEqual(expectedPrice,actualPrice);
        Mock.Assert(() => RollDice(4,6),Occurs.Once());

    }
     
    [TestMethod]
    public void TestRollDice()
    {
        PriceSeries target = new PriceSeries();
        Mock.Arrange(() => RollOneDie(6)).Returns(3);
     
        int[] expectedd6 = {3};
        int[] actuald6 = target.RollDice(1, 6);
        Mock.Assert(() => RollOneDie(6), Occurs.Once());
        Assert.AreEqual(expectedd6.Length,actuald6.Length);
        Assert.AreEqual(expectedd6[0],actuald6[0]);         
    }


     I'm using VS2010, JetBrains ReSharper 7.0.1, and JetBrains dotCover2.2.  

    TestFirstPriceGen() always picks up the mocking and works correctly, whether running it alone, or as part of the UT harness (via Run All Tests or Cover All Tests) - all assertions pass.

    However, that doesn't apply for TestRollOneDie() - no matter how I call it (via running the UT directly, or Run/Cover All Tests), it fails the Mock.Assert call, saying:
    "Expected PriceSeries.RollOneDie(Int32) call on the mock should be once, but it was called 0 time(s)."

    Without that Mock.Assert call, it ignores the mock and calls the original implementation of RollOneDie(), and thus fails 5 out of 6 times.

    What am I doing wrong?
  2. Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 09 Sep 2013 Link to this post

    Hi Peter,

    Could you wrap your system under test and the two unit tests into an repro project and attach it to this ticket, please? That way it would be much faster to resolve this issue.

    Regards,
    Stefan
    Telerik
    Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
  3. DevCraft R3 2016 release webinar banner
  4. Peter
    Peter avatar
    2 posts
    Member since:
    Sep 2013

    Posted 09 Sep 2013 Link to this post

    Stefan,

    Umm... I think the problem was between the keyboard and chair.

    Namely, bugs in the UTs themselves that I only spotted when I was prepping the demo project to attach.

    [TestMethod]
    public void TestFirstPriceGen()
    {
        PriceSeries target = new PriceSeries();
        // mock out dice roll
        int[] mockroll = new int[] {3,5,4,5};
        Mock.Arrange(() => target.RollDice(4, 6)).Returns(mockroll);
          
        double expectedPrice = 698.75;  // dice roll of +3 from initialisation
      
        double actualPrice = target.GetNextPrice();
        Assert.AreEqual(expectedPrice,actualPrice);
        Mock.Assert(() => RollDice(4,6),Occurs.Once());
     
    }

    Which instance's RollDice() method?

    [TestMethod]
    public void TestRollDice()
    {
        PriceSeries target = new PriceSeries();
        Mock.Arrange(() => RollOneDie(6)).Returns(3);
      
        int[] expectedd6 = {3};
        int[] actuald6 = target.RollDice(1, 6);
        Mock.Assert(() => RollOneDie(6), Occurs.Once());
        Assert.AreEqual(expectedd6.Length,actuald6.Length);
        Assert.AreEqual(expectedd6[0],actuald6[0]);        
    }


    Which instance's RollOneDie() method?


    Sorry to waste your time, Stefan - I feel a bit embarrassed to realise that I hadn't specified all the instances that needed to be specified.  Once I fixed those omissions, the UTs run properly every time.

    Could you please mark this thread as solved or the like?
Back to Top