6
public class Business {  
    protected List<BusinessRulesDto> BusinessRules { get; set; }  
}

I tried:

  1. businessMockObject.Protected().SetupSet<List<BusinessRulesDto>>("BusinessRules", ItExpr.IsAny<List<BusinessRulesDto>>()).Verifiable();
    
  2. var businessRulesDtoList = Builder<BusinessRulesDto>.CreateListOfSize(2).Build().ToList();  
    businessMockObject.Protected().SetupGet<List<BusinessRulesDto>>("BusinessRules").Returns(businessRulesDtoList);
    businessMockObject.Protected().SetupSet<List<BusinessRulesDto>>("BusinessRules", ItExpr.IsAny<List<BusinessRulesDto>>()).Verifiable();
    

I've tried lots of things but none of it worked out. I am able to mock protected method but not protected properties.

How can I mock protected properties?

James Z
  • 12,209
  • 10
  • 24
  • 44
  • You could always set the object via reflection. here's a answer on how to do that https://stackoverflow.com/questions/1565734/is-it-possible-to-set-private-property-via-reflection – Marcus Höglund Mar 28 '18 at 06:24
  • 1
    @Tobias, why is it so? Why mocking a protected property means weakness in architecture? – Corio Jan 24 '19 at 17:49

2 Answers2

4

According to documentation

Moq 4.8 and later allows you to set up protected members through a completely unrelated type that has the same members and thus provides the type information necessary for IntelliSense to work. You can also use this interface to set up protected generic methods and those having by-ref parameters:

Create an interface in the test project to encapsulate the protected member to be mocked

public interface IBusinessProtectedMembers {  
    List<BusinessRulesDto> BusinessRules { get; set; }  
}

Then use that with the mock to also take advantage of IntelliSense

var businessRulesDtoList = Builder<BusinessRulesDto>.CreateListOfSize(2).Build().ToList();
businessMockObject.Protected().As<IBusinessProtectedMembers>()
    .Setup(_ => _.BusinessRules)
    .Returns(businessRulesDtoList);

Finally this all hinges on the requirement by Moq that members to be mock/stubbed must be virtual so as to allow the framework to override the member.

Which means Business should look like

public class Business {  
    protected virtual List<BusinessRulesDto> BusinessRules { get; set; }  
}

for the above suggestion to work.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • +1 for the answer. You said protected method/property should be virtual for mocking. How I am able to mock public methods which are not virtual? Namespaces I used are: `using FizzWare.NBuilder; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq;` Is this working because I am using interfaces on top of every class I am mocking? – Ashish Kumar Jaryal Apr 02 '18 at 12:22
2

Mock under the hood creates subclass of target. Whenever target is concrete class (not interface), the methods which you want to mock should be virtual, otherwise subclass has no way to override it and provide Setupped functionality.

tchelidze
  • 8,050
  • 1
  • 29
  • 49
  • 1
    Ok. I am able to mock protected method in the same class: `var eventHookResponseModel = Builder.CreateNew().Build(); businessMockObject.Protected().Setup("SameTabDataUpdate", ItExpr.IsAny()).Returns(eventHookResponseModel).Verifiable(); ` As you pointed out the method `SameTabDataUpdate` is protected and virtual: `protected virtual EventHookResponseModel SameTabDataUpdate(EventHookModel eventHookModel)` – Ashish Kumar Jaryal Mar 28 '18 at 06:59