Moq – Getting the Value Of a Mocked Method Parameter

moq logo

There’s scenarios where we don’t care about the Moq “It.IsAny<>” parameter value being passed into a mocked method but we need to get the value on the way out. For example, take the scenario below. I’m using SQLite to form integration tests and I need to get a handle on the generated ParentWidget.Id to tie back to my Widget FK.

var dbWidget = _mapper.Map(widget);
await _ctx.Widgets.AddAsync(dbWidget);

mockedService.Setup(v => v.CreationOfParentMethod(It.IsAny(), It.IsAny()))
                          .Returns((ParentWidget p, Widget w) => 
                          { myAutoFixureObj.ParentWidgetId = r.Id; return myAutoFixureObj});

For some reason I thought I’d need to break out to an anonymous callback method but it’s pretty simple. My continuing series on Moq.

Hide Endpoints And Schemas from Swagger / OpenAPI

Swagger

I have a requirement to hide a few of the API’s controller endpoints from Swagger along with their respective schemas that aren’t yet ready for public consumption. I still want them to be available for Postman/Newman tests as part of the CI/CD. This can be achieved using the following Swashbuckle filter and MVC convention to successfully hide Swagger endpoints :-

MVC Convention to hide Controllers from Swagger

There’s more Controllers to hide than to show so it makes sense to explicitly specify the Controller names to generate documentation for. This could be improved by using Feature Toggles. My idea at the moment is that the visible controllers will get switched on as they pass testing and are ready for public consumption. Eventually this class will disappear.

Controller visibility

Its then just a case of adding the ActionModelConvention into the startup.cs……

Swagger document configuration

Swashbuckle Filter to hide Schemas

Similar to the Controllers above there are more schemas to hide than to show so I explicitly call out the ones to include in the generated Swagger/OpenAPI doc via a Swashbuckle SchemaFilter. Thanks to the discussion on GitHub….

Remove schemas from Swagger

Its then just a case of adding the filter into the Startup class….

There is the more fine grained approach of decorating each action to exclude with the following attribute…

[ApiExplorerSettings(IgnoreApi = true)]

Due to the amount of operations to exclude it made much more sense to go with omitting the actions by convention.

Moq OData Delta Objects To Test Patch Methods

moq logo

Issue

Following on from my afternoon with Moq I stumbled upon another fun issue. How the hell could I test my API’s PATCH methods? They all make use of OData’s Delta objects.

public async Task<IActionResult> Patch([FromRoute] Guid id, Delta<ViewModels.SomeThing> something)

Solution

It’s actually fairly simple. You just need to create a new Delta object with the correct types then set the delta property value. My “expectedVM” is an autofixture-d object acting as my viewmodel as part of the request body on the PATCH. For extra bonus points you’d replace the “Blah” with an AutoFixture string create as we don’t really care about the value and as good developers we hate magic strings right? 🙂

     var delta = new Delta<ViewModels.Something>(expectedVM.GetType());

            delta.TrySetPropertyValue(nameof(expectedVM.Name), "Blah");
      var result = await myController.Patch(Id, delta);

            var actualModel = ((ObjectResult)result).Value as ViewModels.Something;



            Assert.AreEqual(typeof(OkObjectResult), result.GetType());


            Assert.AreEqual("Blah", actualModel.Name);

Mock a return type of Task and Tuple with Moq

moq logo

Issue

Using Moq I was creating a few unit tests and stumbled across an interesting problem. I needed to mock a call to an async method on a service under test that took in a 2 parameters and returned a tuple of 2 values.

     (dbSomething, error) = await _myService.Create(something, null);

Solution

After a bit of battling I used Moq’s “ReturnAsync”

        _myMockedService.Setup(t => t.Create(It.IsAny<something>(), null))
            .ReturnsAsync((object something, string error) =>
            {
                return (null, "some expected errror");
            });

I’ve removed any business context

System.MissingMethodException: Method not found – Entity Framework

Issue

Encountered the System.MissingMethodException: Method not found with very little else to go on. I noticed as part of the stack trace a reference to an async call on Entity Framework Core Add method.

Solution

The error got me thinking about EF Core and I realised I was using SQLite to test an EF Core project. The version of EF Core was 2.26 whereas my SQLite package was targeting 3.1. A quick downgrade of the SQLite package via Nuget package manager and I was motoring again!