How to mock ResourceGroupCollection using Moq?

74 Views Asked by At

My code is the following:

SubscriptionResource subscription = await armClient.GetDefaultSubscriptionAsync();
var resourceGroup = subscription.GetResourceGroups().FirstOrDefault(rg => rg.Data.Name.Equals(resourceGroupName));

GetResourceGroups() returns an instance of ResourceGroupCollection. When the ResourceGroupCollection is enumerated by SingleOrDefault, I'm trying to get the mock to return a mock instance of a ResourceGroupResource. However, I'm not sure how to do that.

So far I have this code in my Moq test:

this.resourceGroupCollectionMock = new Mock<ResourceGroupCollection>() { CallBase = true };

Mock<ResourceGroupResource> adfResource = new Mock<ResourceGroupResource>();
ResourceGroupData rgData = ResourceManagerModelFactory.ResourceGroupData(resourceIdentifier, resourceGroupName);
adfResource.Setup(x => x.Data).Returns(rgData);

this.subscriptionResourceMock.Setup(x => x.GetResourceGroups()).Returns(this.resourceGroupCollectionMock.Object);

As you can see in my setup, I mocked GetResourceGroups() to return the mock ResourceGroupCollection object. But I'm not sure how to add adfResource to that mock resourceGroupCollectionMock, so that it is returned when the latter is enumerated.

1

There are 1 best solutions below

0
Peter Csala On BEST ANSWER

TL;DR: Unfortunately you can't mock ResourceGroupData properly because ResourceData's Name (1, 2) is not defined as virtual/abstract ;(

//Arrange
const string resourceGroupName = "A";

Mock<ResourceGroupData> data = new();
// data
//     .SetupGet(x => x.Name)
//     .Returns(resourceGroupName); 

// The above commented mock setup would throw NotSupportedException

Mock<ResourceGroupResource> resource = new();
resource
    .SetupGet(x => x.Data)
    .Returns(data.Object);

Mock<Response> response = new();
var pagedResource = Page<ResourceGroupResource>.FromValues(new ResourceGroupResource[] { resource.Object }, null, response.Object);
var pagedResources = Pageable<ResourceGroupResource>.FromPages(new Page<ResourceGroupResource>[] { pagedResource });

Mock<ResourceGroupCollection> collection = new();
collection
    .Setup(x => x.GetAll(It.IsAny<string>(), It.IsAny<int?>(), It.IsAny<CancellationToken>()))
    .Returns(pagedResources);

Mock<SubscriptionResource> subscription = new();    
subscription
    .Setup(x => x.GetResourceGroups())
    .Returns(collection.Object);

//Act
var actual = subscription.Object.GetResourceGroups()
    .FirstOrDefault();
    //.FirstOrDefault(rg => rg.Data.Name.Equals(resourceGroupName)); 

// The above commented line would throw NullReferenceException

//Assert
Assert.NotNull(actual);

So, if you don't use the Name property in your predicate (like in the above sample) then you can mock/fake the rest of the classes.