MOQ- Setting up and verifying a generic method with Func argument - moq

I have a third party interface which I want to mock its methods. To make my purpose clear consider the following IFoo interface which has a generic method like M2. One of M2 arguments is of type Func.
public interface IFoo
{
bool M1<T>();
bool M2<T>(T arg, Func<T, string> func);
}
If I set up the M2 method as:
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.M2(It.IsAny<It.IsAnyType>(),It.IsAny<Func<It.IsAnyType, string>>())).Returns(true);
mock.Object.M2("arg1", s => s);
mock.Verify(foo => foo.M2(It.IsAny<It.IsAnyType>(), It.IsAny<Func<It.IsAnyType, string>>()));
then verify will fail. But if it is set up and verified with a specific type like string then it works:
mock.Setup(foo => foo.M2(It.IsAny<string>(), It.IsAny<Func<string, string>>())).Returns(true);
mock.Object.M2("arg1", s => s);
mock.Verify(foo => foo.M2(It.IsAny<string>(), It.IsAny<Func<string, string>>()));
The problem is that the actual type of T passed to my Mock is an internal class defined in that third party library. So I can't set up and verify with a specific type like the above-mentioned one.
Am I missing something in my first set up or verify or it is a well-known issue which has not been addressed yet?
I am using moq 4.13.1 and my test project is .Net Core 3.1

Rather than
It.IsAny<Func<It.IsAnyType, string>>()
for the Func parameter, try
(Func<It.IsAnyType, string>) It.IsAny<object>()
Working example:
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.M2(It.IsAny<It.IsAnyType>(), (Func<It.IsAnyType, string>) It.IsAny<object>())).Returns(true);
mock.Object.M2("arg1", s => s);
mock.Verify(foo => foo.M2(It.IsAny<It.IsAnyType>(), (Func<It.IsAnyType, string>) It.IsAny<object>()));
As far as I know Moq isn't able to match the Func<> type parameters using the It.IsAnyType matcher.

It seems that Moq fixed this bug in v4.15
https://github.com/moq/moq4/pull/1092

Related

Mock.Verify does not identify call made to mock service provided by IServiceProvider

I'm trying to write an integration test for a service method. The test compiles and runs without error, but it says that the number of calls that match the predicate are 0.
Test setup:
[TestCase]
public void Save_Submission_Processing_And_ClientGroupMapping_Type()
{
Mock<ISubmissionRepository> submissionRepositoryMock = new Mock<ISubmissionRepository>();
submissionRepositoryMock.Setup(x => x.GetOne(It.IsAny<Guid>())).Returns(QueryResult<Submission>.Ok(new Submission()));
IServiceCollection services = new ServiceCollection();
services.AddSingleton(x => submissionRepositoryMock.Object);
ClientGroupMappingService clientGroupMappingService = new ClientGroupMappingService(services.BuildServiceProvider());
clientGroupMappingService.ProcessClientGroupMappingImport(Guid.NewGuid());
submissionRepositoryMock.Verify(c => c.Save(It.Is<Submission>(d => d.SubmissionStatus == SubmissionStatus.Processing)), Times.Once);
}
Unit under test:
public class ClientGroupMappingService : IClientGroupMappingService
{
private readonly ISubmissionRepository _submissionRepository;
public ClientGroupMappingService(IServiceProvider serviceProvider)
{
_submissionRepository = serviceProvider.GetRequiredService<ISubmissionRepository>();
}
public void ProcessClientGroupMappingImport(Guid submissionID)
{
Submission submission = _submissionRepository.GetOne(submissionID).Value;
submission.SubmissionStatus = SubmissionStatus.Processing;
_submissionRepository.Save(submission);
// ..other stuff
}
}
Moq.MockException :
Expected invocation on the mock once, but was 0 times: c => c.Save(It.Is<Submission>(d => (int)d.SubmissionStatus == 2))
So Verify should see that the call was made to Save, and the param passed to Save matches the condition in the supplied predicate. My knee-jerk reaction is that once I pull the object out of the mock using submissionRepositoryMock.Object, I am no longer tracking the Mock, so calls to the Object are not going to register on the Mock. But if this is the case, what is the correct way to verify that my method made the required call?
The issue was in the "// ...other stuff" that I took out for brevity.
Later on in the method, the SubmissionStatus is updated again, and Mock.Verify only seems to be evaluating the REFERENCE to the object that was passed into the Save call as opposed to the VALUE, as all of the Invocations of Save show that it was called with SubmissionStatus.Success (which isn't actually true).
Hope this makes sense and helps anyone with a similar problem.

Moq.MockVerificationException not public xUnit Assert.Throws

I am testing a method which will call another method if certain parameters are certain values and not if they are other.
I was using Moq's Verify to test this. However when I use the xUnit to see if the method is not called when sending parameters with data which should not make the method call the 2nd method.
Problem is that I cannot do
mockObject.Verify();
Assert.Throws<Moq.MockVerificationException>(()=>mockObject.Method());
I changed from MSTest to xUnit because the support for throws was built in and I had to have the ExpectedException attribute decorating my test method before.
I tried to cast the Moq non-public exception to the public parent Moq.MoqException but that will throw an error.
so I think I may have to do:
try {moqObj.Verify();}
catch(Moq.Exception mve)
{
Assert.SomethingIsException();
}
As I understand, you're just trying to verify whether certain methods are called or not? If so, try this:
var theThing = new Mock<IThing> ();
theThing.Verify (x => x.DoSomething ("a"), Times.Never);
theThing.Verify (x => x.DoSomething ("b"), Times.Once);
If you need to invoke another method after the first method is called, you could use a callback:
theThing.Setup (x => x.DoSomething ("a")).Callback (() => {});

When to specify certain Setups in Moq

I'm trying to follow this Get Started example for testing with Moq. I'm able to duplicate the examples within my own testing project and can get my tests to pass (testing my service where my context is injected). However, what I don't understand is WHEN to use each of the following Setup calls:
var mockSet = new Mock<DbSet<Blog>>();
mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
Can someone explain in very basic terms as to when each of these should be used?
For example, It seems that if the method in my service that I'm testing uses an expression, I need to do the 2nd setup call above (I've done some trial and error by removing and re-inserting these calls). I've been to the Moq documentation as well as MSDN for Table-TEntity and I still don't see it. Perhaps because I don't have a strong grasp of the Linq namespace.
TL;DR - When using an Entity Framework DBContext dependency, you will need perform these Setups on any DBSet which you intend to mock, specifically to return fake data to any LINQ queries on the DBSet. All 4 setups should be done for each mocked DbSet - this can be done generically in a helper method.
In more Detail:
In general, with Strict mode off, Setup is only required on methods that you actually want to Mock. In this case, if you haven't done a Setup on a method which is invoked during your Unit Test, Moq will instead provide default behaviour for any method which hasn't been explicitly Setup, which typically is to return the default(T) of any expected return type, T. For classes, the default is null, which isn't really going to help any during testing of classes dependent on a Mocked EF DbContext.
The specific example you have provided is the standard mocked setup for an Entity Framework DbSet, which then allows you to provide fake data for this specific DbSet (DbSet<Blog>), by providing an alternative IQueryable<Blog> from a List<Blog> collection (as opposed to the usual concrete RDBMS implementation).
A suggestion would be to move the DbSetmock code into your standard unit test plumbing setup framework / toolkit, to create a helper method like:
public static Mock<IDbSet<T>> GetMockedDbSet<T>(IList<T> fakeData) where T : class, new()
{
var data = fakeData.AsQueryable();
var mockSet = new Mock<IDbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
return mockSet;
}
Which you can then set up on your Mock DBContext, as follows:
var mockContext = new Mock<IMyDbContext>();
var mockBlogDbSet = GetMockedDbSet<Blog>(new List<Blog>{... fake data here ...});
mockContext.Setup(c => c.Blogs).Returns(mockBlogDbSet.Object);
var sut = new SomeClassIWantToTest(mockContext.Object); // Inject dependency into Ctor
sut.DoSomething();...

How can I let Rebus determine an endpoint for an interface and not for an implementation of that interface

When I Send an instance created by AutoMapper.Mapper.DynamicMap() I run into an error where Rebus seems to want to determine an endpoint for proxy type returned by DynamicMap. This instance will contain an implementation of T assuming T is an interface type.
Is there a way in which I can let Rebus determine an endpoint for the interface type T and not for the implementing type returned by DynamicMap()?
I tried playing around with IDetermineMessageOwnership but had no luck so far.
public static void Send<T>(this IBus bus, object source)
{
var message = Mapper.DynamicMap<T>(source);
bus.Send<T>(message);
}
Thanks in advance!
Sure! In your case, you could create your own implementation of IDetermineMessageOwnership which is the service that Rebus uses to map a message type to an endpoint.
If you want to leverage Rebus' existing logic, you could decorate any chosen strategy and extend it with a keep-looking-at-all-implemented-interfaces-until-one-can-be-mapped strategy like so:
Configure.With(adapter)
.(...)
.MessageOwnership(o => o.FromRebusConfigurationSection())
.Decorators(d => d.AddDecoration(DecorateOwnershipMapping)))
.CreateBus()
.Start();
where DecorateOwnershipMapping would install a decorator on top of whatever is configured like so:
void DecorateOwnershipMapping(ConfigurationBackbone b)
{
b.DetermineMessageOwnership = new CustomizedEndpointMapper(b.DetermineMessageOwnership);
}
and a possible implementation could look like this:
class CustomizedEndpointMapper : IDetermineMessageOwnership
{
readonly IDetermineMessageOwnership wrappedEndpointMapper;
public CustomizedEndpointMapper(IDetermineMessageOwnership wrappedEndpointMapper)
{
this.wrappedEndpointMapper = wrappedEndpointMapper;
}
public string GetEndpointFor(Type messageType)
{
var mappingCandidates = new[] {messageType}
.Concat(messageType.GetInterfaces())
.ToList();
foreach (var typeToTry in mappingCandidates)
{
try
{
return wrappedEndpointMapper.GetEndpointFor(typeToTry);
}
catch{}
}
throw new InvalidOperationException(string.Format("Could not determine the owner of message of type {0} - attempted to map the following types: {1}",
messageType, string.Join(", ", mappingCandidates)));
}
}
thus iterating through the concrete type as well as all inherited interface types when trying to determine the owning endpoint.
In your case, I believe this would work flawlessly when determining the message owner. Only problem is that the serializer will most likely complain, because the dynamically generated type cannot be recognized again when the message is received.
Hence, this trick requires customization of the serializer as well. If you're using the (default) JSON serializer, you might get away with some custom resolvers like so:
Configure.With(...)
.(...)
.Serialization(s => s.UseJsonSerializer()
.AddNameResolver(CustomNameResolver)
.AddTypeResolver(CustomTypeResolver))
.(...)
where CustomNameResolver and CustomTypeResolver are methods that must then take care of mapping the type to a type name and mapping the type name to a type that can then be deserialized into. In order to make this work with AutoMapper, you'll probably need to either
a) somehow use AutoMapper to look up the type of the received message and return that type from CustomTypeResolver, or
b) customize the serializer to have AutoMapper somehow participate in generating the object to be returned
but I must admit that I'm unsure whether the last part will play out smoothly.
A final note: if you succeed in making this work, I suggest you pack up your configuration spells into a reusable extension method on RebusConfigurer so that your endpoints can just go
Configure.With(...)
.(...)
.UseMyFunkyAutoMapperMessagesJustTheWayILikeIt()
.CreateBus().Start();
in all your Rebus endpoints...
I'll appreciate it if you'll let me know how this works out for you! :)

ASP.NET MVC - Unit testing, mocking HttpContext without using any mock framework

Since I'm having problem with unit testing RenderPartialViewToString() with Moq framework (ASP.NET MVC - Unit testing RenderPartialViewToString() with Moq framework?), I'm thinking about getting my controller directly, without using Moq for these particular test, however, how do I mocks (or set) the HttpContext for my test without using any Moq framework?
I need to able to do something similar to this, without Moq of course:
var mockHttpContext = new Mock<ControllerContext>();
mockHttpContext.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("n1\\test");
mockHttpContext.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
Thank you very much.
If your controller need authentication info from HttpContext, I would:
Create a new class that wraps the calls you care about. Looks like you want Name and IsAuthenticated. The new class can be AuthenticationService or something.
In the methods/properties in AuthenticationService, call into the real HttpContext, like HttpContext.Current.user.Identity.Name.
Create an interface over the new
AuthenticationService with the
public methods/properties you care about.
Inject the IAuthenticationService
into your controller under test in
the constructor. Looks like you may already be doing that with other dependencies in the controller.
Now you can mock
IAuthenticationService and it's
return values without needing to
call into the real HttpContext.
Here are more details from a blog post I did http://www.volaresystems.com/Blog/post/2010/08/19/Dont-mock-HttpContext.aspx. I'm using RhinoMocks instead of Moq, but the concept is the same for staying away from HttpContext.
You can mock it as follows and declare a stringBuilder object that accepts the output.
var response = new Mock<HttpResponseBase>();
response.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(y => _stringBuilder.Append(y));
var url = new Uri("http://localhost/Home/");
var request = new Mock<HttpRequestBase>();
request.Setup(x => x.Url).Returns(url);
request.Setup(x => x.ApplicationPath).Returns("");
var httpContext = new Mock<HttpContextBase>();
httpContext.Setup(x => x.Request).Returns(request.Object);
httpContext.Setup(x => x.Response).Returns(response.Object);
_controllerContext = new Mock<ControllerContext>();
_controllerContext.Setup(x => x.HttpContext).Returns(httpContext.Object);
_homeController = autoMock.Create<HomeController>();
_homeController.ControllerContext = _controllerContext.Object;
You execute your action as follows:
var action=_homeController.Action(<parameters>);
action.ExecuteResult();
and now your stringbuilder object i.e _stringBuilder will have the result output whatever type it is and you can test it.

Resources