Moq CreateInstance fails when constructor has dependencies using Func<T> - c#

public class MyService
{
private readonly ISomething _something;
private readonly Func<IRarelyGetUsed> _rarelyGetUsed;
public MyService(ISomething something, Func<IRarelyGetUsed> rarelyGetUsed)
{
_something = something;
_rarelyGetUsed = rarelyGetUsed;
}
}
We use Autofac for our IOC and found we can get big performance gains (when under load) using the Func<T> approach because those dependencies don't get resolved until they are used, and in some scenarios certain dependencies are not used.
We are also using Moq for some unit testing.
var _container = new AutoMocker();
var _service = _container.CreateInstance<MyService>();
At this point it blows up - System.NullReferenceException : Object reference not set to an instance of an object.
Anyone know how to tell Moq to play nicely with Func dependencies?
Note that if I change Func<IRarelyGetUsed> to IRarelyGetUsed there's no exception.
Edit: Turns out the nuget package was pretty old - after updating the package https://github.com/tkellogg/Moq.AutoMocker this is now working.
However, there's one more problem to solve -
_container.GetMock<Func<IRarelyGetUsed>>().Setup(p => p().DoSomething(It.IsAny<string>())).Returns(true).Verifiable();
Trying to setup the result of the above method result in - Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.InvocationExpression'
Edit 2:
var serviceMock = _container.GetMock<IRarelyGetUsed>();
serviceMock.Setup(r => r.DoSomething()).Returns(someData);
_container.GetMock<Func<IRarelyGetUsed>>().Setup(s => s()).Returns(serviceMock.Object);
The above now works, however it requires setting up both the Func<IRarelyGetUsed> and IRarelyGetUsed - would be nice if it was only necessary to do one, otherwise there's more overhead per test.

You can automatically wire up a Func<T> for every T with AutoMocker doing something like this:
public void RegisterFuncs(AutoMocker autoMocker, IEnumerable<Type> types)
{
var use = typeof(AutoMocker).GetMethods()
.First(t => t.Name == "Use" &&
t.GetGenericArguments().First().Name == "TService");
var get = typeof(AutoMocker).GetMethod("Get");
foreach (var type in types)
{
// _.container.Use<Func<T>>()
var typedUse = use.MakeGenericMethod(typeof(Func<>).MakeGenericType(type));
// _container.Get<T>()
var typedGet = get.MakeGenericMethod(type);
var target = Expression.Constant(autoMocker);
var call = Expression.Call(target, typedGet);
// () => _container.Get<T>()
var lambda = Expression.Lambda(call);
// _.container.Use<Func<T>>(() => _container.Get<T>())
typedUse.Invoke(autoMocker, new object[] { lambda.Compile() });
}
}
// Then call with your AutoMocker instance and the interfaces you want to wire up
var types = typeof(SomeNamespace.ISomeInterface).Assembly.GetExportedTypes()
.Where(t => t.IsInterface && !t.ContainsGenericParameters);
RegisterFuncs(yourAutoMocker, types);
Run this in your test setup just after creating a container.
Note: to make the above work for Lazy<T>, you have to instantiate the Lazy<T> with a Func<T>, so you'll need something like the following:
public void RegisterLazys(AutoMocker autoMocker, IEnumerable<Type> types)
{
var use = typeof(AutoMocker).GetMethods()
.First(t => t.Name == "Use" &&
t.GetGenericArguments().First().Name == "TService");
var get = typeof(AutoMocker).GetMethod("Get");
foreach (var type in types)
{
// Lazy<T>
var lazyT = typeof(Lazy<>).MakeGenericType(type);
// _.container.Use<Lazy<T>>()
var typedUse = use.MakeGenericMethod(lazyT);
// _container.Get<T>()
var typedGet = get.MakeGenericMethod(type);
var target = Expression.Constant(autoMocker);
var call = Expression.Call(target, typedGet);
// () => _container.Get<T>()
var lambda = Expression.Lambda(call);
// _.container.Use<Lazy<T>>(new Lazy<T>(() => _container.Get<T>()));
typedUse.Invoke(autoMocker, new object[] { Activator.CreateInstance(lazyT, lambda.Compile()) });
}
}

Have you tried using Lazy<T> instead of Func<T> to achieve the lazy loading you desire? It may play better with Moq than Func does.
Documentation on Lazy

Related

Failed to register Instance in AutoFac?

I want to use the existing mock instance of my project in AutoFac. I do not want to rewrite my PROD code. So I found something AutoFac which is not working. I think I am missing something.
I have tried below code.
public AboutTideEditorMockTest () {
aboutTideService = new AboutTideEditorService (iAboutTideEditorRepository.Object, exceptionLogServiceMock.Object);
aboutTideServiceWithNullParam = new AboutTideEditorService (null, exceptionLogServiceMock.Object);
}
//This is my test case
[FactWithAutomaticDisplayName]
public void Test1 () {
var cb = new ContainerBuilder ();
var studyLoaderMock = new Mock<IAboutTideEditorService> ().Object;
var studyLoaderMock1 = iAboutTideEditorRepository.Object;
var studyLoaderMock2 = exceptionLogServiceMock.Object;
cb.RegisterInstance (studyLoaderMock).As<IAboutTideEditorService> ();
cb.RegisterInstance (studyLoaderMock1).As<IAboutTideEditorRepository> ();
cb.RegisterInstance (studyLoaderMock2).As<IExceptionLogService> ();
var container = cb.Build ();
using (var scope = container.BeginLifetimeScope ()) {
var component = scope.Resolve<AboutTideEditorService> ();
responseData = component.AddAboutTideContent (applicationUser, aboutTide);
Assert.Equal (ProcessStatusEnum.Invalid, responseData.Status);
}
}
I want to use the existing mock instance that I am passing to "RegisterInstance". When I am trying to debug my test case I am getting "responseData" null. I am not able to go inside in AddAboutTideContent.
You are not setting up the mock return value and you need to resolve IAboutTideEditorService rather than AboutTideEditorService.
You also need to generate the mocks differently. There is no need to change the production code though!
Do it like this:
[FactWithAutomaticDisplayName]
public void Test1() {
var cb = new ContainerBuilder();
var studyLoaderMock = new Mock<IAboutTideEditorService>();
var studyLoaderMock1 = new Mock<IAboutTideEditorRepository>(); // you don't need that when resolving only IAboutTideEditorService
var studyLoaderMock2 = new Mock<IExceptionLogService>(); // you don't need that when resolving only IAboutTideEditorService
cb.RegisterInstance(studyLoaderMock.Object).As<IAboutTideEditorService>();
cb.RegisterInstance(studyLoaderMock1.Object).As<IAboutTideEditorRepository>(); // you don't need that when resolving only IAboutTideEditorService
cb.RegisterInstance(studyLoaderMock2.Object).As<IExceptionLogService>(); // you don't need that when resolving only IAboutTideEditorService
var container = cb.Build();
studyLoaderMock
.Setup(x => x.AddAboutTideContent(It.IsAny<YourTypeHereForParameterA>,
It.IsAny<YourTypeHereForParameterB>)
.Returns(new MyResponseDataType()); // add the right types here necessary, I can't tell which types they are because I am not seeing the functions code
using (var scope = container.BeginLifetimeScope()) {
var component = scope.Resolve<IAboutTideEditorService>(); // changed to IAboutTideEditorService
responseData = component.AddAboutTideContent(applicationUser, aboutTide);
Assert.Equal(ProcessStatusEnum.Invalid, responseData.Status);
}
}
Your function call was returning null because that's the default behavior of a mock with Moq = MockBehavior.Loose. If you want a function of a mock to return a specific value for non explicit or explicit parameters, you have to call Setup(delegate) and Returns(objectInstance) or Returns(Func<ObjectType>).
In general your test-setup doesn't make much sense. You are basically only registering mocks with the Autofac-Container which makes the container itself irrelevant for your tests. Using IoC for tests is usually only required when you are directly testing against the implementations rather than mocks. Those tests are called Integration-Tests.
It would make more sense like this:
[FactWithAutomaticDisplayName]
public void Test1() {
var cb = new ContainerBuilder();
var studyLoaderMock1 = new Mock<IAboutTideEditorRepository>();that when resolving only IAboutTideEditorService
var studyLoaderMock2 = new Mock<IExceptionLogService>();
var studyLoader = new AboutTideEditorService(studyLoaderMock1.Object, studyLoaderMock2.Object);
cb.RegisterInstance(studyLoader).As<IAboutTideEditorService>();
var container = cb.Build();
// now setup the functions of studyLoaderMock1 and studyLoaderMock2
// required for your function `AddAboutTideContent` from `IAboutTideEditorService` to work.
using (var scope = container.BeginLifetimeScope()) {
var component = scope.Resolve<IAboutTideEditorService>(); // changed to IAboutTideEditorService
responseData = component.AddAboutTideContent(applicationUser, aboutTide);
Assert.Equal(ProcessStatusEnum.Invalid, responseData.Status);
}
}
Keep in mind that I am assuming here the order of the parameters required for AboutTideEditorService. For more information on how to setup mocks with Moq take a look here.

Dynamically passing T into a method

I have followed this post to create a writable options class for .Net Core WebAPI. I use this class for updating my appsettings.json file.
I want to create these writable options classes dynamically. For example, I have multiple options classes like OptionsA, OptionsB and so on. They can be configured in appsettings.json and should only be injected when they are present in that file.
So far so good, now my problem is ConfigureWritable has a type parameter T. My problem is, when my code finds OptionsA in the appsettings.json file, how do I supply the type to the ConfigureWritable method?
Here's what I have so far:
private void AddOptionalServices(IServiceCollection services, ServiceSettings serviceSettings)
{
foreach (var serviceSetting in serviceSettings.Services)
{
var serviceType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => t.Name == serviceSetting.Name).FirstOrDefault();
var settingsType = (Type)serviceType.GetProperty("ServiceType").GetValue(serviceType, null);
services.AddSingleton(typeof(IHostedService), serviceType);
services.ConfigureWritable<settingsType>(Configuration.GetSection("")); //Problem lies here
}
}
settingsType is a property that is returned from serviceType.
EDIT: Second attempt based on Lasse's comment:
private void AddOptionalServices(IServiceCollection services, ServiceSettings serviceSettings)
{
foreach (var serviceSetting in serviceSettings.Services)
{
var serviceType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => t.Name == serviceSetting.Name).FirstOrDefault();
var settingsType = (Type)serviceType.GetProperty("ServiceType").GetValue(serviceType, null);
services.AddSingleton(typeof(IHostedService), serviceType);
var method = typeof(IServiceCollection).GetMethod("ConfigureWritable"); //returns null
var methods = typeof(IServiceCollection).GetMethods(); //returns empty enumeration
var generic = method.MakeGenericMethod(settingsType);
generic.Invoke(this, null);
}
}
As you can see, I don't get the method back when using GetMethod.

How to configure Moq via builder

I'm trying out Moq and the builder pattern to set up services for testing CRM plugins. On the builder I have a ConfigureMock<T>(Expression<Action<Mock<T>>>) to inject individual configurations. My problem is that once a service is .Setup(), I would like to get the entity the service worked on via .Callback<Entity>(), but I cannot assign it to a local variable in the test, because I can't do assignments in the callback expression.
Here is the config:
private readonly Dictionary<Type, object> MockServices = new Dictionary<Type, object>();
public PluginContextBuilder ConfigMock<T>(Expression<Action<Mock<T>>> setupConfig) where T : class
{
object svc = null;
if (MockServices.TryGetValue(typeof(T), out svc))
{
var mockSvc = (Mock<T>) svc;
Action<Mock<T>> setup = setupConfig.Compile();
setup(mockSvc);
}
return this;
}
And here's an example how I would like to configure in the test (but will not compile):
var createdFanClub = null;
var context = new PluginContextBuilder()
.ConfigMock<IOrganizationService>(c =>
c.Setup(s =>
s.Create(It.IsAny<Entity>()))
.Returns(fanclubGuid))
.Callback<Entity>(a => createdFanClub = a))
If I create an additional Action<Entity> which does the assignment, it works, but I don't think it's practical, in case I have multiple entities, I will need to make just as many assignments for them:
Entity createdFanClub = null;
Action<Entity> assign = a => createdFanClub = a;
var context = new PluginContextBuilder()
.ConfigMock<IOrganizationService>(c =>
c.Setup(s =>
s.Create(It.IsAny<Entity>()))
.Returns(fanclubGuid))
.Callback<Entity>(assign))
Not sure what you try to accomplish. If the goal is to have a builder, which has a handle to all the mocks needed, then why not just return the mock itself, and configure it as one normally will do:
builder.GetMock<IOrganizationService>().Setup....
That will prevent you to chain calls on the same builder (as I see you are trying to do), but it's not a big trade-off, and will simplify your setups.

Using Ninject MockingKernel Moq how to inject multiple mocks for the same interface

The C# class that I wish to test accepts IEnumerable instances of the same interface. I use Ninject for dependency injection. How would I inject mocks into the IEnumerable using Ninject MockingKernel Moq
public class Foo: IFoo
{
private readonly Dictionary<ContextType, IBar> _bars;
public Foo(IEnumerable<IBar> bars)
{
_bars= bars.ToDictionary(x => x.ContextType);
}
}
public interface IBar
{
ContextType ContextType { get; }
void DoStuff();
}
public enum ContextType
{
Local,
Site,
Test
}
This is how my regular binding looks like
//assume _kernel is StandardKernel
_kernel.Bind<IFoo>().To<MyFoo>();
_kernel.Bind<IBar>().To<Bar1>(); //ContextType.Site
_kernel.Bind<IBar>().To<Bar2>(); //ContextType.Local
_kernel.Bind<IBar>().To<Bar3>(); //ContextType.Test
Setting up mocks like below injects only the last mock into Foo (as supposed to injecting 3 mocks)
//using _kernel = new MoqMockingKernel()
_kernel.Bind<IFoo>().To<MyFoo>();
var bar1Mock = _kernel.GetMock<IBar>();barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site);
var bar2Mock = _kernel.GetMock<IBar>();barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local);
var bar3Mock = _kernel.GetMock<IBar>();barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test);
_foo = _kernel.Get<IFoo>();
Any help is appreciated. Thanks
Why don't just instantiate Foo by hand, if you are Unit Testing it?
var bar1Mock = _kernel.GetMock<IBar();
barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site);
var bar2Mock = _kernel.GetMock<IBar>();
barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local);
var bar3Mock = _kernel.GetMock<IBar>();
barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test);
// simply create new instance, what is a point o
var target = new Foo(new[]{barMock1.Object, bar2Mock.Object, bar3Mock.Object });
But if a understand you right, you want IEnumerable<IBar> bars to be filled by a Ninject?
Then you need to bind actual collection using Ninject:
var allBars = new []{new Bar1(), new Bar2(), new Bar3()};
kernel.Bind<IEnumerable<IBar>>().ToConstant(allBars);
Or, try actually array of IBar instead of IEnumerable<IBar>, and leave your binding as is:
_kernel.Bind<IFoo>().To<MyFoo>();
_kernel.Bind<IBar>().To<Bar1>(); //ContextType.Site
_kernel.Bind<IBar>().To<Bar2>(); //ContextType.Local
_kernel.Bind<IBar>().To<Bar3>();
public class Foo: IFoo
{
private readonly Dictionary<ContextType, IBar> _bars;
public Foo(IBar[] bars)
{
_bars= bars.ToDictionary(x => x.ContextType);
}
}
According to manual, this should work.
Update: Bind to actual mock instances, and after resolve IFoo as usual:
var bar1Mock = _kernel.GetMock<IBar();
barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site);
var bar2Mock = _kernel.GetMock<IBar>();
barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local);
var bar3Mock = _kernel.GetMock<IBar>();
barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test);
_kernel.Bind<IBar>().ToConstant(bar1Mock.Object);
_kernel.Bind<IBar>().ToConstant(bar2Mock.Object);
_kernel.Bind<IBar>().ToConstant(bar3Mock.Object);
foo = _kernel.Get<IFoo>();
Update2: Try this way
_kernel.Bind<IBar>().ToMethod( x => bar1Mock.Object);
_kernel.Bind<IBar>().ToMethod( x => bar2Mock.Object);
_kernel.Bind<IBar>().ToMethod( x => bar3Mock.Object);
I have this working now. _kernel needs to be reset before another unique mock of the same interface is requested. This code below works
var bar1Mock = _kernel.GetMock<IBar();barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site);
_kernel.Reset();
var bar2Mock = _kernel.GetMock<IBar>();barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local);
_kernel.Reset();
var bar3Mock = _kernel.GetMock<IBar>(); barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test);
_kernel.Reset();
_kernel.Bind<IBar>().ToConstant(bar1Mock.Object);
_kernel.Bind<IBar>().ToConstant(bar2Mock.Object);
_kernel.Bind<IBar>().ToConstant(bar3Mock.Object);
Thanks
Running into the same issue. Answers above didn't help.
Here is one solution bellow, but it is not ideal.
Using kernel.Reset(); does not seem right.
Code like
var bar1Mock = _kernel.GetMock<IBar()
barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site);
var bar2Mock = _kernel.GetMock<IBar>();
barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local);
var bar3Mock = _kernel.GetMock<IBar>();
barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test);
_kernel.Bind<IBar>().ToMethod( x => bar1Mock.Object);
_kernel.Bind<IBar>().ToMethod( x => bar2Mock.Object);
_kernel.Bind<IBar>().ToMethod( x => bar3Mock.Object);
foo = _kernel.Get<IFoo>();
Still returns link to the same (last) mock. Maybe I'm missing something?
I do want to use mocking kernel, but so far the best I got is:
var barMock1 = new Moq.Mock<IBar>();
barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site);
var barMock2 = new Moq.Mock<IBar>();
barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local);
var bar1Mock3 = new Moq.Mock<IBar>();
barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test);
_kernel.Bind<IBar>().ToMethod(s => barMock1.Object);
_kernel.Bind<IBar>().ToMethod(s => barMock2.Object);
_kernel.Bind<IBar>().ToMethod(s => barMock3.Object);
This should work for more or less simple objects, but if there are dependencies in Ibar we'll have to resolve the manually and using ninject for that would be desirable. So any better ideas how to get different objects mocks or some way to set 'scope'?

How do I verify a method was called?

I have a ICreateService class that has dependency on ITicketApiAdapter. I've tried registering a mock ITicketAdaper so that it gets injected when I create an anonymous create service.
So, in setup, I have this register for the ticket adapter:
Fixture.Register(() =>
{
var ticketApiAdapter = new Mock<ITicketApiAdapter>();
ticketApiAdapter
.Setup( x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()))
.Returns(new SaveResult
{
Success = true,
Id = Fixture.CreateAnonymous<Guid>().ToString()
});
return ticketApiAdapter;
});
Fixture.Register(() => new CreateService(Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>().Object));
From my understanding, that should "freeze" both the ICreateService and Mock<ITicketApiAdapter> so that when I request an anonymous instance, it's the one I registered.
I have a test that looks like this:
[TestMethod]
public void CreateServiceCallsAddTicketComment()
{
var apiTicketAdapter = Fixture.CreateAnonymous<Mock<ITicketApiAdapter>>();
var createTicketRequest = Fixture.CreateAnonymous<CreateTicketComment>();
var createService = Fixture.CreateAnonymous<CreateService>();
var results = createService.CreateTicketComment(createTicketRequest);
apiTicketAdapter
.Verify(x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()),
Times.Once());
Assert.IsTrue(results.All(x => x.Success));
Assert.IsTrue(results.All(x => x.Errors.Count == 0));
}
I expect the apiTicketAdapter to be the one I registered so that I can verify the method is called. If I step through, the TicketApiAdapter is called, but Moq says it wasn't.
Edit
This is the error I get:
CreateServiceCallsAddTicketComment threw exception:
Moq.MockException: Expected invocation on the mock once, but was 0
times: x => x.AddTicketComment(It.IsAny(), It.IsAny(),
It.IsAny())
Configured setups: x => x.AddTicketComment(It.IsAny(),
It.IsAny(), It.IsAny()), Times.Never No
invocations performed.
When you Register a code block, that code block is going to be invoked every time the Fixture instance resolves the requested type. This means that it's not frozen. If you want to Freeze something, one of the Freeze overloads are often easier to use.
Better yet, since you seem to be using Moq, may I suggest using the AutoMoq extension?
That would enable you to rewrite the test to something like this:
[TestMethod]
public void CreateServiceCallsAddTicketComment(new AutoMoqCustomization());
{
var fixture = new Fixture().Customize()
var apiTicketAdapter = fixture.Freeze<Mock<ITicketApiAdapter>>();
ticketApiAdapter
.Setup( x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()))
.Returns(new SaveResult
{
Success = true,
Id = Fixture.CreateAnonymous<Guid>().ToString()
});
var createTicketRequest = fixture.Freeze<CreateTicketComment>();
var createService = fixture.CreateAnonymous<CreateService>();
var results = createService.CreateTicketComment(createTicketRequest);
apiTicketAdapter
.Verify(x => x.AddTicketComment(
It.IsAny<User>(),
It.IsAny<Customer>(),
It.IsAny<TicketComment>()),
Times.Once());
Assert.IsTrue(results.All(x => x.Success));
Assert.IsTrue(results.All(x => x.Errors.Count == 0));
}
That's assuming that CreateTicketRequest uses Constructor Injection or Property Injection.

Categories