1

MOQ questions often get people pointing back to the documents , which is cool and all but I think I need some help understanding what this error comes from ( maybe my knowledge of lambda expressions is off )

I have a MOQ test

var mockTicket = new Mock<Ticket>();
        mockTicket.Setup(tix => tix.Total).Returns(var expectedResult = 5); 
        cashRegister.PendingTickets.Add(mockTicket.Object);


        //act 
        var actual = cashRegister.CloseTicket(mockTicket.Object);
        // FYI . close ticket returns the total of the tickets hence this is logical to the point that the 
        // ticket is the price being returned. 

        //assert
        Assert.Equals(actual, expectedResult);

and my errors are

System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: tix => tix.Total

and also Total is just a get

       public decimal Total
    {
        get
        {
            return Decimal.Round(ItemsOrdered.Sum(x => x.Price + x.Tax), 2);
        }
    }
h4mme7
  • 91
  • 10
  • 1
    I believe you need to mock the interface, not the class in that case... as in, I think you need an ITicket interface that Ticket implements. – jkerak Feb 15 '16 at 20:28
  • The error tells you everything you need to know. `Total` is non-virtual, so it's invalid to set it up. [Moq cannot mock non-virtual members](http://stackoverflow.com/a/11738166/1698557). – Patrick Quirk Feb 15 '16 at 20:37

1 Answers1

2

To do the mocking you would need to have an ITicket interface to pass into your method, then your cashRegister doesn't need a concrete Ticket and you can use a known good value for Total.

Additionally, you don't need the var set in the return. You would be able to use:

var mockTicket = new Mock<ITicket>();
mockTicket.Setup(tix => tix.Total).Returns(5);

Additionally, you would need to change cashRegister.PendingTotal and cashRegister.CloseTicket to have ITicket in the signature instead of Ticket.

Alternatively, you can arrange a concrete Ticket class to return a known good value for Total.


Additionally, I wouldn't alter the Ticket class to have a virtual Total property on it, just to facilitate this testing, you would be allowing the tests to pollute the code needlessly.

NikolaiDante
  • 18,469
  • 14
  • 77
  • 117