I have a simple console application which uses Autofac as IoC container.
class Program
{
static IContainer container;
static void Main(string[] args)
{
container = Configure();
Run();
}
private static void Run()
{
using (var scope = container.BeginLifetimeScope())
{
var t = scope.Resolve<ITest1>();
var s = t.TestMethod1("");
Console.WriteLine(s);
}
}
private static IContainer Configure()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass1>()
.As<ITest1>();
builder.RegisterType<TestClass2>()
.As<ITest2>();
return builder.Build();
}
}
The application calls the method "TestMethod1" in "TestClass1".
public interface ITest1
{
string TestMethod1(string s);
}
public class TestClass1 : ITest1
{
ITest2 f;
public TestClass1(Func<ITest2> test2Factory)
{
f = test2Factory();
}
public string TestMethod1(string s)
{
var r = string.Empty;
r = f.TestMethod2(s);
r += ":TestMethod1";
return r;
}
}
TestClass1 has a dependency on TestClass2 which declares a delegate factory for Autofac to use with the TestClass1 constructor.
public interface ITest2
{
string TestMethod2(string s);
}
public class TestClass2 : ITest2
{
public delegate TestClass2 Factory();
public virtual string TestMethod2(string s)
{
return ":TestMethod2";
}
}
This all works as expected - Autofac resolves the TestClass2 dependency, and I get the output ":TestMethod2:TestMethod1".
Now I want to mock TestClass2 using Moq and the Autofac.Extras.Moq extensions. I add the following method to the console application, and call it from the Program Main method.
private static void Test()
{
using (var mock = AutoMock.GetLoose())
{
mock.Mock<TestClass2>()
.Setup(t => t.TestMethod2(""))
.Returns(":NOT_TEST_METHOD2");
var s = mock.Create<TestClass1>();
var r = s.TestMethod1("cheese");
Console.WriteLine(r);
}
}
Now I get the output ":TestMethod1" when I expect ":NOT_TEST_METHOD2:TestMethod1". It seems the mock has not been called. This is confirmed when I step through the code.
I have also tried resolving the mock using mock.Provide(), as has been suggested elsewhere (see below). Still no luck.
var wc = Moq.Mock.Of<TestClass2>(f => f.TestMethod2("") == ":NOT_TEST_METHOD2");
Func<string, ITest2> factory = x => wc;
mock.Provide(factory);
This seems like a really simple scenario but I've not found a working answer anywhere. Can anyone see what I'm doing wrong?
Thanks for any help!
I don't use the AutoMock support, but I do know my Autofac, so I can give it a shot.
It looks like TestClass1 takes an ITest2 and not a TestClass2 in its constructor, I'm guessing if you switched to this:
mock.Mock<ITest2>()
.Setup(t => t.TestMethod2(""))
.Returns(":NOT_TEST_METHOD2");
...then it might work.
Thanks Travis. Your suggestion didn't work for me, but it made me think about the issue differently and taking a step back made me realise I was looking for a complex solution where one wasn't required. Namely, that only Moq was needed, Autofac AutoMock extensions were not. The following code worked:
private static void Test()
{
Func<ITest2> func = () =>
{
var x = new Mock<ITest2>();
x.Setup(t => t.TestMethod2("")).Returns(":NOT_TEST_METHOD2");
return x.Object;
};
var s = new TestClass1(func);
var r = s.TestMethod1("");
}
The question was answered by this post Using Moq to Mock a Func<> constructor parameter and Verify it was called twice.
Related
How can I write unit tests to test my hub?
Here is my Hub Class:
public class MyHub : Hub
{
private readonly ILifetimeScope _scope;
private readonly IMyProvider _provider;
public MyHub(ILifetimeScope scope)
{
scope = _scope;
_provider = _scope.Resolve<IMyProvider>();
}
public void BroadcastMessage(int messageId)
{
var myMessage = _provider.GetFromDb(messageId);
Clients.All.broadcastMessage(myMessage);
}
}
I'm using moq and xunit, i've tried things like this:
//arrange
var messageId = 1;
var message = "test";
var providerMock = new Mock<IMyProvider>();
providerMock.Setup(x => x.GetFromDb(messageId).Returns(test);
var scopeMock = new Mock<ILifetimeScope>();
scopeMock.Setup(x => x.Resolve<IMyProvider>()).Returns(providerMock.Object);
var hub = new MyHub(scopeMock.Object);
//act
hub.BroadcastMessage(messageId);
//assert
providerMock.Verify(x => x.GetFromDb(messageId), Times.Once());
but this causes an error:
System.NotSupportedException : Unsupported expression: x => x.Resolve()
Extension methods (here: ResolutionExtensions.Resolve) may not be used in setup / verification expressions.
I found this answer: https://stackoverflow.com/a/49523868/3708225 that says I can do something like
using (var mock = AutoMock.GetLoose()){
var providerMock = new Mock<IMyPRovider>();
providerMock.Setup(x=>x.GetFromDb(messageId)).Returns(message);
mock.Provide(providerMock.Object);
var lifetime = mock.Create<ILifetimeScope>();
using (var scope = lifetimeScope.BeginLifetimeScope()){
var innerMockProvider = scope.Resolve<IMyProvider>();
//rest of test
}
}
but AutoMock.GetLoose().Provide() isn't defined
This is probably not the answer you are looking for. But a workaround would be not to mock lifetimescope but simply setup a autofac container to use in these tests.
Secondly do you need to inject the lifetimescope directly in your class? Maybe use a decorator pattern where you let the decorator create the lifetimescope and resolve your class and invoke it. Getting rid of the lifetimescope in your myhub class will make your life easier. Make it the job of some other class to control the lifetimescope. Else you will need to repeat this pattern in all your other classes as well. You should instead inject IMyProvider.
This is how I solved this:
If I change my hub to the following:
public class MyHub : Hub
{
private readonly <Func>IMyProvider _provider;
public MyHub(<Func>IMyProvider provider)
{
_provider = provider;
}
public void BroadcastMessage(int messageId)
{
var provider = _provider();
var myMessage = provider.GetFromDb(messageId);
Clients.All.broadcastMessage(myMessage);
}
}
Now i can mock Func<IMyProviider> to return what I need and ignore the lifetime scope
I have a following problem. I register my components and initialize them in Unity like this (example is for a Console application):
public class SharePointBootstrapper : UnityBootstrapper
{
...
public object Initialize(Type type, object parameter) =>
Container.Resolve(type,
new DependencyOverride<IClientContext>(Container.Resolve<IClientContext>(parameter.ToString())),
new DependencyOverride<ITenantRepository>(Container.Resolve<ITenantRepository>(parameter.ToString())));
public void RegisterComponents()
{
Container
.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString())
.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString())
.RegisterType<ITenantRepository, DocumentDbTenantRepository>(SharePointClientContext.Online.ToString())
.RegisterType<ITenantRepository, JsonTenantRepository>(SharePointClientContext.OnPremise.ToString());
}
}
public enum SharePointClientContext
{
Online,
OnPremise
}
class Program
{
static void Main(string[] args)
{
...
bootstrap.RegisterComponents();
var bla = bootstrap.Initialize(typeof(ISharePointManager), SharePointClientContext.Online);
}
}
So, I register my components in MVC, WCF, Console etc. once with RegisterComponents() and initialize them with Initialize().
My question is, if I want to initialize specific named registration at runtime, from e.g. user input, can it be done otherwise as the code presented (with InjectionFactory or similar)?
This code works fine, but I'm not happy with its implementation. I have a feeling that it could be written in RegisterComponents() instead of Initialize() so that it accepts a parameter of some type, but I don't know how to do it.
Or, is maybe my whole concept wrong? If so, what would you suggest? I need to resolve named registration from a parameter that is only known at runtime, regardless of the technology (MVC, WCF, Console, ...).
Thanks!
Instead of doing different registrations, I would do different resolves.
Let's say that you need to inject IClientContext, but you want different implementations depending on a runtime parameter.
I wrote a similiar answer here. Instead of injecting IClientContext, you could inject IClientContextFactory, which would be responsible for returning the correct IClientContext. It's called Strategy Pattern.
public interface IClientContextFactory
{
string Context { get; } // Add context to the interface.
}
public class SharePointOnlineClientContext : IClientContextFactory
{
public string Context
{
get
{
return SharePointClientContext.Online.ToString();
}
}
}
// Factory for resolving IClientContext.
public class ClientContextFactory : IClientContextFactory
{
public IEnumerable<IClientContext> _clientContexts;
public Factory(IClientContext[] clientContexts)
{
_clientContexts = clientContexts;
}
public IClientContext GetClientContext(string parameter)
{
IClientContext clientContext = _clientContexts.FirstOrDefault(x => x.Context == parameter);
return clientContext;
}
}
Register them all, just as you did. But instead of injecting IClientContext you inject IClientContextFactor.
There also another solution where you use a Func-factory. Look at option 3, in this answer. One may argue that this is a wrapper for the service locator-pattern, but I'll leave that discussion for another time.
public class ClientContextFactory : IClientContextFactory
{
private readonly Func<string, IClientContext> _createFunc;
public Factory(Func<string, IClientContext> createFunc)
{
_createFunc = createFunc;
}
public IClientContext CreateClientContext(string writesTo)
{
return _createFunc(writesTo);
}
}
And use named registrations:
container.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString());
container.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString());
container.RegisterType<IFactory, Factory>(
new ContainerControlledLifetimeManager(), // Or any other lifetimemanager.
new InjectionConstructor(
new Func<string, IClientContext>(
context => container.Resolve<IClientContext>(context));
Usage:
public class MyService
{
public MyService(IClientContextFactory clientContextFactory)
{
_clientContextFactory = clientContextFactory;
}
public void DoStuff();
{
var myContext = SharePointClientContext.Online.ToString();
IClientContextclientContext = _clientContextFactory.CreateClientContext(myContext);
}
}
Using AutoFixture with the AutoFixture.AutoMoq package, I sometimes find tests that weren't configured to correctly test the thing they meant to test, but the problem was never discovered because of the default (Loose) Mock behavior:
public interface IService
{
bool IsSomethingTrue(int id);
}
void Main()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
var service = fixture.Freeze<Mock<IService>>();
Console.WriteLine(service.Object.IsSomethingTrue(1)); // false
}
I'd like to make Mocks get created with Strict behavior, so we're forced to call Setup() for the methods we expect to be called. I can do this for each individual mock like this:
fixture.Customize<Mock<IService>>(c => c.FromFactory(() => new Mock<IService>(MockBehavior.Strict)));
But after combing through source code for AutoMoqCustomization() and the various ISpecimenBuilder and other implementations, I'm pretty lost as to the best way to just make all Mocks get initialized with strict behavior. The framework appears to be very flexible and extensible, so I'm sure there's a simple way to do this--I just can't figure out how.
There's no simple built-in feature that will enable you to do something like that, but it shouldn't be that hard to do.
Essentially, you'd need to change MockConstructorQuery so that it invokes the constructor that takes a MockBehavior value, and pass in MockBehavior.Strict.
Now, you can't change that behaviour in MockConstructorQuery, but that class is only some 9-10 lines of code, so you should be able to create a new class that implements IMethodQuery by using MockConstructorQuery as a starting point.
Likewise, you'll also need to create a custom ICustomization that does almost exactly the same as AutoMoqCustomization, with the only exception that it uses your custom IMethodQuery with strict mock configuration instead of MockConstructorQuery. That's another 7 lines of code you'll need to write.
All that said, in my experience, using strict mocks is a bad idea. It'll make your tests brittle, and you'll waste a lot of time mending 'broken' tests. I can only recommend that you don't do this, but now I've warned you; it's your foot.
For those interested, down below you can find #MarkSeemann's reply translated into code. I am pretty sure it does not cover all use cases and it was not heavily tested. But it should be a good starting point.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Moq;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoMoq;
using Ploeh.AutoFixture.Kernel;
namespace ConsoleApplication1
{
public class StrictAutoMoqCustomization : ICustomization
{
public StrictAutoMoqCustomization() : this(new MockRelay()) { }
public StrictAutoMoqCustomization(ISpecimenBuilder relay)
{
// TODO Null check params
Relay = relay;
}
public ISpecimenBuilder Relay { get; }
public void Customize(IFixture fixture)
{
// TODO Null check params
fixture.Customizations.Add(new MockPostprocessor(new MethodInvoker(new StrictMockConstructorQuery())));
fixture.ResidueCollectors.Add(Relay);
}
}
public class StrictMockConstructorMethod : IMethod
{
private readonly ConstructorInfo ctor;
private readonly ParameterInfo[] paramInfos;
public StrictMockConstructorMethod(ConstructorInfo ctor, ParameterInfo[] paramInfos)
{
// TODO Null check params
this.ctor = ctor;
this.paramInfos = paramInfos;
}
public IEnumerable<ParameterInfo> Parameters => paramInfos;
public object Invoke(IEnumerable<object> parameters) => ctor.Invoke(parameters?.ToArray() ?? new object[] { });
}
public class StrictMockConstructorQuery : IMethodQuery
{
public IEnumerable<IMethod> SelectMethods(Type type)
{
if (!IsMock(type))
{
return Enumerable.Empty<IMethod>();
}
if (!GetMockedType(type).IsInterface && !IsDelegate(type))
{
return Enumerable.Empty<IMethod>();
}
var ctor = type.GetConstructor(new[] { typeof(MockBehavior) });
return new IMethod[]
{
new StrictMockConstructorMethod(ctor, ctor.GetParameters())
};
}
private static bool IsMock(Type type)
{
return type != null && type.IsGenericType && typeof(Mock<>).IsAssignableFrom(type.GetGenericTypeDefinition()) && !GetMockedType(type).IsGenericParameter;
}
private static Type GetMockedType(Type type)
{
return type.GetGenericArguments().Single();
}
internal static bool IsDelegate(Type type)
{
return typeof(MulticastDelegate).IsAssignableFrom(type.BaseType);
}
}
}
Usage
var fixture = new Fixture().Customize(new StrictAutoMoqCustomization());
I'm trying build out our logging framework using EntLib Logging and use attribute to indicate which class/method should be logged. So I think Interception would be a good choice. I'm a super noob to Ninject and Interception and I's following the tutorial at Innovatian Software on how to use interception via attributes. But when I run the app, BeforeInvoke and AfterInvoke was never called. Help Please, Thank You!
using System;
using System.Diagnostics;
using System.Collections.Generic;
using Castle.Core;
using Ninject;
using Ninject.Extensions.Interception;
using Ninject.Extensions.Interception.Attributes;
using Ninject.Extensions.Interception.Request;
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<ObjectWithMethodInterceptor>().ToSelf();
var test= kernel.Get<ObjectWithMethodInterceptor>();
test.Foo();
test.Bar();
Console.ReadLine();
}
}
public class TraceLogAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<TimingInterceptor>();
}
}
public class TimingInterceptor : SimpleInterceptor
{
readonly Stopwatch _stopwatch = new Stopwatch();
protected override void BeforeInvoke(IInvocation invocation)
{
Console.WriteLine("Before Invoke");
_stopwatch.Start();
}
protected override void AfterInvoke(IInvocation invocation)
{
Console.WriteLine("After Invoke");
_stopwatch.Stop();
string message = string.Format("Execution of {0} took {1}.",
invocation.Request.Method,
_stopwatch.Elapsed);
Console.WriteLine(message);
_stopwatch.Reset();
}
}
public class ObjectWithMethodInterceptor
{
[TraceLog] // intercepted
public virtual void Foo()
{
Console.WriteLine("Foo - User Code");
}
// not intercepted
public virtual void Bar()
{
Console.WriteLine("Bar - User Code");
}
}
I figured it out, I missed the part where I've to disable auto module loading and manually load the DynamicProxy2Module to the kernel. Here's the change to the code:
//var kernel = new StandardKernel(); //Automatic Module Loading doesn't work
var kernel = new StandardKernel(new NinjectSettings() { LoadExtensions = false }, new DynamicProxy2Module());
Hope this help someone else.
This seems like something simple but I can't seem to get it to work.
I have a class with a Save method that simply calls another method ShouldBeCalled(). I want to verify that if I call Save() that the other method ShouldBeCalled() is executed at least once. I thought that I could do the following.
public class ClassA
{
public virtual void Save()
{
ShouldBeCalled();
}
public virtual void ShouldBeCalled()
{
//This should get executed
}
}
[TestFixture]
public class ClassA_Test
{
[Test]
public void Save_Should_Call_ShouldBeCalled()
{
var mockClassA = new Mock<ClassA>();
mockClassA.Object.Save();
mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());
}
}
But I get the exception "Expected invocation on the mock at least once, but was never performed: x => x.ShouldBeCalled()"
It is just a guess but Is Moq overriding the Save() method with it's own version which ignores anything I have inside the real object's Save() method.
You are having this problem because you are mocking what you are testing. This doesn't make sense.
You are correct that Moq will replace the implementation of your method with its own. The reason is you are supposed to use Moq to mock things the class you are testing calls, not the class you are testing itself.
This test would be appropriate if your code were designed thusly:
public class ClassA
{
BusinessLogicClass bl;
public ClassA(BusinessLogicClass bl)
{
this.bl = bl;
}
public void Save()
{
bl.ShouldBeCalled();
}
}
public class BusinessLogicClass
{
public virtual void ShouldBeCalled()
{
//This should get executed
}
}
And here is the correct test of that method now:
[TestFixture]
public class ClassA_Test
{
[Test]
public void Save_ShouldCallShouldBeCalled()
{
//Arrange
var mockBLClass = new Mock<BusinessLogicClass>();
mockBLClass.Setup(x => x.ShouldBeCalled()).Verifyable();
//Act
ClassA classA = new ClassA(mockBLClass.Object);
classA.Save();
//Assert
mockBLClass.VerifyAll();
}
}
The key lesson here is that you mock/stub what your test needs to run, not what you are testing itself.
Hope this helps,
Anderson
Try using the CallBase = true and then false. I ran your code and it works.
var mockClassA = new Mock<ClassA>();
mockClassA.CallBase = true;
mockClassA.Object.Save();
mockClassA.CallBase = false;
mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());
Yes, this can be done. However, you need to add a line of code to have Moq track whether or not the ShouldBeCalled method was indeed called.
Something like the following will work:
var mockClassA = new Mock<ClassA>();
mockClassA.Setup(x => x.ShouldBeCalled()).Verifiable();
mockClassA.Object.Save();
mockClassA.Verify(x => s.ShouldBeCalled(), Times.AtLeastOnce());
The Setup method sets up expectations. When you call Verify, you are asking Moq to verify these expectations. If you don't make a Setup call to create expectations for the ShouldBeCalled method, then Moq doesn't consider it to be trackable and will therefore fail hard when you try to Verify it.
You can stub methods in the system under test using CallBase.
[TestFixture]
public class ClassA_Test
{
[Test]
public void Save_Should_Call_ShouldBeCalled()
{
// Arrange
var mockClassA = new Mock<ClassA>();
mockClassA.CallBase = true; // this will call real methods unless the method is mocked/stubbed.
mockClassA.Setup(a => a.ShouldBeCalled());
// Act
mockClassA.Save();
// Assert
mockClassA.Verify(a => a.ShouldBeCalled(), Times.Once());
}
}