0

I am trying to mock(Moq lib) an abstract class (In this example, X class). Inside this class, it is a property which has been assigned as a [ForeignKey("xId")]. The classes are as follows, and I try to mock this X class.

But I get an error

"System.NotSupportedException: 'Invalid setup on a non-virtual (overridable in VB) member: mock => mock.SubX'"

.

Anyone has any idea what is the best way to mock such property?

public abstract class X
{
   [ForeignKey("xId")]
   public SubX SubX {get; set;}
}

public class SubX
{
   [Key]
   public int Id {get; set;}
}

var mockedX = Mock.Of<X>(a => a.SubX.Id == 10);
Sahil Sharma
  • 1,813
  • 1
  • 16
  • 37
ShrnPrmshr
  • 353
  • 2
  • 5
  • 17
  • 1
    XY problem. Why are you trying to mock this class in the first place? There are plenty of related questions if you research that error message, what have you tried? – CodeCaster Jan 22 '19 at 12:35
  • I have a class which uses this class as a return value for a repo. and I need to mock that repo and use this class as a return value. _mockedXRepository.Setup(f => f.GetX(It.IsAny – ShrnPrmshr Jan 22 '19 at 12:40
  • You shouldn't be mocking the class, and if you are insistent on doing so then you must mark the property as `virtual`, as the exception suggests. What you should instead do is mock the interface which contains the contract member who returns a derived type of `X` so it returns an instance of derived `X`.containing your test data. – ColinM Jan 22 '19 at 12:42
  • 1
    You don't mock return values, you mock dependencies. You can simply return a `new DerivedFromX { SubX = new SubX { Id = 10 } }` from that mocked call. – CodeCaster Jan 22 '19 at 12:42
  • @ColinM This is legacy code, and I try to not touch it at all. – ShrnPrmshr Jan 22 '19 at 12:48
  • Does the implementation which returns `X` or `SubX` implement an interface or mockable dependency? – ColinM Jan 22 '19 at 12:49
  • @CodeCaster, Yes I did that but I was more wondering how can I mock this abstract class and why I can not assign anything to that specific property. Because I can easily assign others. so I am trying to understand the reasons back of that more to solve my problem. – ShrnPrmshr Jan 22 '19 at 12:49
  • To answer that question: https://stackoverflow.com/a/21793891/5062791 – ColinM Jan 22 '19 at 12:51
  • @ColinM no, not at all. It has been written badly. No interface. I need to mock every single thing or the worst scenario create new classes for using those abstract classes – ShrnPrmshr Jan 22 '19 at 12:52
  • Considering the legacy scenario, here's a worthy read as patterns are the usual go-to when refactoring, as you shouldn't just be changing properties to `virtual` for the sake of a test https://pdfs.semanticscholar.org/1aa8/ba2e3cd596f3c501e0966530ab24c6bb190e.pdf – ColinM Jan 22 '19 at 12:54

1 Answers1

1

Use a non-abstract class inheriting from X:

class XMock : X
{
}

var mockedX = new XMock(); 
Elton Santana
  • 950
  • 3
  • 11
  • 22