Ninject Get<T> with constructor argument - c#

Here is my Module:
public class LoggerModule : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<NLogLogger>()
.WithConstructorArgument(
typeof(Type),
x => x.Request.ParentContext.Plan.Type);
}
}
So as you can see the NLogLogger is expecting the Type to be passed into the constructor.
This is my Unit Test:
[Test]
public void ResolveLoggerDependency()
{
var module = new LoggerModule();
var kernal = new StandardKernel(module);
var service = kernal.Get<ILogger>(new ConstructorArgument("type", typeof(int)));
Assert.That(service, Is.Not.Null);
}
It is throwing a null reference error on the kernal.Get<ILogger> so I can only assume I am not passing the constructor value correctly. How can I pass in a Type when using Get<T>?

So, this question as it seems relates to your other question.
The requirement in that question was to inject into NLogLogger the type of the object into which the it will be injected.
The registration in this case is assuming that this interface ILogger will not be resolved outside the context of a parent class into which it will be injected. And you are getting the exception because there is no parent class context when you directly attempt to resolve the ILogger interface.
I am assuming that in your unit test, your would like to test that this registration actually work. I would suggest the following:
First, create a class the you will use in your tests:
public class TestClass
{
private readonly ILogger m_Logger;
public TestClass(ILogger logger)
{
m_Logger = logger;
}
public ILogger Logger
{
get { return m_Logger; }
}
}
And then use such class in your unit tests like this:
[Test]
public void ResolveLoggerDependency()
{
var module = new LoggerModule();
var kernal = new StandardKernel(module);
var test_object = kernal.Get<TestClass>();
Assert.That(test_object.Logger, Is.Not.Null);
}
You can further verify that the NLogLogger actually used the TestClass class's name to construct the NLog logger. This might require the use of Reflection though, I am not sure.

In your Load method you can just set it up using Bind<ILogger>().To<NLogLogger>();

Related

How to setup AutoFixture.AutoMoq to moq all contructor parameters?

I am using AutoFixture to mock an external library that doesn't always implement interfaces, but has a default ctor without parameters.
Currently, I am using Moq/AutoMoq framework like that:
mocker.GetMock<HeavyDependency>()
.Setup(x => x.GetData())
.Returns("TEST DATA");
I want to have the same behaviour with AutoFixture.AutoMoq. My code:
namespace AutoFixtureNUnit.TestsCs
{
public class HeavyDependency1
{
public HeavyDependency1() => Debug.WriteLine("HeavyDependency1");
}
public class HeavyDependency2
{
public HeavyDependency2() => Debug.WriteLine("HeavyDependency2");
}
public class MyClassWithHeavyDependency
{
private readonly HeavyDependency1 dep1;
private readonly HeavyDependency2 dep2;
public MyClassWithHeavyDependency() => Debug.WriteLine("MyClassWithHeavyDependency default.");
public MyClassWithHeavyDependency(HeavyDependency1 h1, HeavyDependency2 h2)
{
Debug.WriteLine("MyClassWithHeavyDependency injected.");
dep1 = h1;
dep2 = h2;
}
}
[TestFixture]
public class TestClass
{
private Fixture _fixture;
private Mock<HeavyDependency1> _heavyMock;
MyClassWithHeavyDependency _sut;
[SetUp]
public void SetUp()
{
_fixture = new Fixture();
_fixture
.Customize(new ConstructorCustomization(typeof(MyClassWithHeavyDependency), new GreedyConstructorQuery()))
.Customize(new AutoMoqCustomization(){ConfigureMembers = false});
_heavyMock = new Mock<HeavyDependency1>();
_fixture.Inject(_heavyMock.Object);
_sut = _fixture.Create<MyClassWithHeavyDependency>();
}
[Test]
public void TestMethod()
{
Assert.Pass("Your first passing test");
}
}
}
MyClassWithHeavyDependency has a ctor that takes dependent objects and code above calls that ctor.
So far so good. I am injecting the Mock of the dependent object and verifying calls.
The problem:
For the mocks that are Injected, the constructor is called with the Mock like: {Mock<AutoFixtureNUnit.TestsCs.HeavyDependency1:00000001>.Object}.
However, for all other types it is called with the parameter of {AutoFixtureNUnit.TestsCs.HeavyDependency2}. Which is not what I want and is not used by the current tests. Not a Moq object, right?
It is mocking my own interfaces as well.
Question:
Can I somehow specify that AutoFixture.AutoMoq should mock all ctor parameters that are not manually mocked by me?
Because Freezing/injecting every single one is not different from manual mock setup and requires a lot of code changes every time I add ctor parameter.
Actually, I can see HeavyDependency1 ctor called as well. Seems strange.

wrapping a static class/method in order to unit test it?

I've got a static class that I am using for logging:
public static class myLogger
{
public static ErrorLogging(string input)
{
//dostuff
}
}
The way I am using it is:
public class myClassthatDoesStuff
{
...
myLogger.ErrorLogging("some error ocurred");
...
}
How can I moq the myLogger class in order to be able to unit test it and ensure that the ErrorLogging method was executed? Is it possible to do this without setting any parameters in the constructor (constructor injection)? myClassthatDoesStuff requires that there are no parameters in the constructor.
This blog post describes the exact same scenario - you have an old static logging method and want to use it in testable code.
Wrap the static class in a non-static class - not just for testing, but for general use.
Extract the methods of your new non-static class into an interface.
Wherever you would have depended on the static class, depend on the interface instead. For example, if class DoesSomething requires the function in your static class, do this:
public interface ILogger
{
void ErrorLogging(string input);
}
public class MyClassthatDoesStuff
{
private readonly ILogger _logger;
public MyClassthatDoesStuff(ILogger logger)
{
_logger = logger;
}
}
This gives you two benefits:
You can unit test your old static class (assuming that it has no state and doesn't depend on anything that has any state) (although if that's the case I suppose you could unit test it anyway.)
You can unit test code that will use that static class (by removing the direct dependency on that static class.) You can replace ILogger with a mocked class, like one that adds your error messages to a list.
class StringLogger : List<string>, ILogger
{
public void ErrorLogging(string input)
{
Add(input);
}
}
var testSubject = new MyClassthatDoesStuff(new StringLogger());
A simpler option doesn't require creating an interface and an adapter class. You can create a delegate which is like an interface for just a method.
In the case of the logger, it would be
delegate void Logging ErrorLoggingMethod(string input);
Using it looks similar to using an interface:
public class MyClassthatDoesStuff
{
private readonly ErrorLoggingMethod _logger;
public MyClassthatDoesStuff(ILogger logger)
{
_logger = logger;
}
public void DoSomethingThatLogs()
{
// _logger is a method
_logger("Log something");
}
}
This is even easier to mock and test
string loggedMessage = null;
ErrorLoggingMethod fakeLogger = (input) => loggedMessage = input;
You can inject the fake logger into the class you're testing. If that class calls the logger, the method assigns whatever was logged to the variable. Then you can assert whatever was logged or just that anything was logged.
If your app uses a dependency injection/IoC container, you can register the delegate just like you would an interface. Here's an example.
If you can not change it from a static to a non-static class, wrap it with a non-static class...
void Test()
{
string testString = "Added log";
var logStore = new List<string>();
ILogger logger = new MyTestableLogger(logStore);
logger.ErrorLogging(testString);
Assert.That(logStore.Any(log => log==testString));
}
public interface ILogger
{
void ErrorLogging(string input);
}
public class MyTestableLogger : ILogger
{
public MyTestableLogger(ICollection<string> logStore)
{
this.logStore = logStore;
}
private ICollection<string> logStore;
public void ErrorLogging(string input)
{
logStore.Add(input);
MyLogger.ErrorLogging(input);
}
}
public static class MyLogger
{
public static void ErrorLogging(string input)
{
// Persist input string somewhere
}
}
You can do it using Microsoft's Shims
Assuming that Your Project is called ConsoleApplication1.
First of all go to your unit test project references, right click on assembly that contains myClassthatDoesStuff class and chose 'Add Fakes Assembly'.
Unit test with shims will look like:
[TestClass()]
public class MyClassthatDoesStuffTests
{
[TestMethod()]
public void ImportansStuffTest()
{
using (ShimsContext.Create())
{
bool logCalled = false;
ConsoleApplication1.Fakes.ShimmyLogger.ErrorLoggingString =
(message) => logCalled = true;
new myClassthatDoesStuff().ImportansStuff();
Assert.IsTrue(logCalled);
}
}
}
You can do it with Typemock Isolator.
It allows you to avoid all this amount of wrappers and interfaces and to do it that simple:
[TestMethod]
public void TestLogging()
{
//Arrange
Isolate.WhenCalled(() => myLogger.ErrorLogging("")).CallOriginal();
//Act
var foo = new myClassthatDoesStuff();
foo.DoStuff();
//Assert
Isolate.Verify.WasCalledWithAnyArguments(() => myLogger.ErrorLogging(""));
}

Mock Autofac.IComponentContext with unit tests c#

I am trying to mock IComponentContext with NSubstitute as below:
[TestClass()]
public class SyncRepositoryFactoryTests
{
private IComponentContext _container;
private SyncRepositoryFactory _factory;
[TestInitialize]
public void Initialize()
{
_container = Substitute.For<IComponentContext>();
_factory = new SyncRepositoryFactory(_container);
}
[TestMethod]
public void Get_SyncRepositoryOfITestEntity_Success()
{
var repository = Substitute.For<IRepository<TestEntity>>();
_container.Resolve<IRepository<TestEntity>>().Returns(repository);
var result = _factory.Get<ITestEntity>();
Assert.IsNotNull(result);
Assert.IsTrue(result is ISyncRepository<ITestEntity>);
}
public interface ITestEntity
{
}
public class TestEntity : ITestEntity
{
}
}
but I get an exception:
ComponentNotRegisteredException: The requested service
'Hvb.eMarketAdvisor.Repository.SharePoint.IRepository`1[[Hvb.eMarketAdvisor.
Repository.SharePoint.Tests.Units.SyncRepositoryFactoryTests+TestEntity,
Hvb.eMarketAdvisor.Repository.SharePoint.Tests.Units,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' has not been registered.
To avoid this exception, either register a component to provide the service,
check for service registration using IsRegistered(), or use the ResolveOptional()
method to resolve an optional dependency.
As I try to create a mock why does IComponentContext try to resolve dependency?
Because Resolve<>() is an extension method and so you're just executing the extension method, not mocking its call. You need to mock the call that the extension method calls.
As the commenters above have said, if you're mocking your DI container, something is wrong with your design.
Old question but if anyone comes here looking for how to it do for whatever your reason is, as of Autofac 4.9.2 the following should work for you. Obviously if you need more logic you can get fancy with the substitutions.
public interface ICalculate
{
bool ProcessData();
}
public class ReallyCoolCalculate : ICalculate
{
public bool ProcessData()
{
return 2 + (2 * 3) == 8;
}
}
public void GetCalculateFromAutoFac()
{
var calculate = new ReallyCoolCalculate();
var componentContext = Substitute.For<IComponentContext>();
var componentRegistration = Substitute.For<IComponentRegistration>();
componentContext.ComponentRegistry.TryGetRegistration(Arg.Any<Service>(), out Arg.Any<IComponentRegistration>()).Returns(true);
componentContext.ResolveComponent(Arg.Any<IComponentRegistration>(), Arg.Any<IEnumerable<Parameter>>()).Returns(calculate);
var calculateFromAutoFac = componentContext.Resolve<ICalculate>();
}

Calling functions on intercepted method invocations in Simple Injector

What I am trying to achieve is to intercept the injection of a class, and call a specific method on the class to alter it's behaviour.
I have implemented the interceptor class that is given on the SimpleInjector website, and this is working, so I am able to get some functionality running when the class is intercepted.
My container is registering it as such:
container.InterceptWith<MyInterceptor>(type => type == typeof(IMyClass));
The class I am intercepting on looks as such:
public class MyClass : IMyClass
{
private IAnotherClass m_class;
public MyClass(IAnotherClass _class)
{
m_class = _class;
}
public void MethodToCall()
{
//changes properties on class
}
}
My interceptor class looks as such:
public class MyInterceptor : IInterceptor
{
private readonly ILogger logger;
public MyInterceptor(ILogger logger)
{
this.logger = logger;
}
public void Intercept(IInvocation invocation)
{
var watch = Stopwatch.StartNew();
// Calls the decorated instance.
invocation.Proceed();
var decoratedType = invocation.InvocationTarget.GetType();
logger.Trace(string.Format("{0} executed in {1} ms.",
decoratedType.Name, watch.ElapsedTicks));
}
}
What I am trying to achieve is to call a method on the intercepted IMyClass. So in the interceptor, call MyClass.MethodToCall()
I have tried to do something like this in the Intercept() method:
var classIntercepted = invocation.ReturnValue;
MethodInfo method = invocation.InvocationTarget.GetType().GetMethod("MethodToCall");
object magicValue = method.Invoke(classIntercepted, null);
But, the invocation.ReturnValue is not returning the MyClass instance, but rather the IAnotherClass instance
Why don't you use a decorator instead of using interception? This is often much easier, more maintainable and faster.
Here's an example:
public class PropSetMyClassDecorator : IMyClass
{
private MyClass decoratee;
public PropSetMyClassDecorator(MyClass decoratee) {
this.decoratee = decoratee;
}
public void MethodToCall() {
this.decoratee.SetConnectionString();
this.decoratee.MethodToCall();
}
}
You can register this decorator as follows:
container.Register<IMyClass, PropSetMyClassDecorator>();
Do note that instead of registering MyClass, we only register the decorator. Since the decorator directly depends on MyClass (not on the interface) MyClass will be automatically resolved by Simple Injector.
Yet another option is to register an initializer as follows:
container.RegisterInitializer<MyClass>(instance => {
instance.SetConnectionString();
});
The initializer delegate will be called every time after a MyClass instance is constructed. The behavior is a bit different in this case, since the method isn't called every time, but only during construction. Usually however, this should be sufficient, since you should normally not change a service during runtime, since you are complicating things.
Ok, found a solution fairly shortly after posting the question.
I changed my Intercept function to be the following:
public void Intercept(IInvocation invocation)
{
// Calls the decorated instance.
invocation.Proceed();
var classIntercepted = invocation.InvocationTarget;
MethodInfo method = invocation.InvocationTarget.GetType().GetMethod("SetConnectionString");
method.Invoke(classIntercepted, null);
}

How to Inject Log4Net ILog implementations using Unity 2.0

Ultimately this has to do with setting up log4Net but generically the problem is not logging specific.
Generically what I am trying to figure out is how to do, in Microsoft Unity 2.0, something equivalent to what one gets with the Castle.Facilities.Logging.LoggingFacility. Namely the ability to declare a dependency on a logger and have the logger initialized with the Type of the object into which it is being injected.
In the spirit of a test is worth a thousand words, here is what I need:
class Logger_IOC_Tests
{
//[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
/* Configuration Magic probably involiving registering either
* a custom IDependencyResolverPolicy or BuilderStrategy
* goes here...
*/
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
interface ILogger
{
Type GetUserType();
}
class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}
public Type GetUserType()
{
return _type;
}
}
class LoggerUser
{
public readonly ILogger Logger;
public LoggerUser(ILogger logger)
{
Logger = logger;
}
}
I don't know if this what you are looking for, but I saw it a few months ago and was reminded of it when I saw your question. I have not used Unity, so I can't really compare what you have posted with what is at the link. Hopefully it will be useful to you:
http://davidkeaveny.blogspot.com/2011/03/unity-and-log4net.html
I've been trying to achieve the same result of being able to insert correctly configured ILog instances into a dependency using constructor injection with Unity.
In the end, I wrote my own "log4net" unity extension to do exactly this (in part inspired by a blog post that another answerer, Kenneth Baltrinic, wrote).
This allows you to register the extension once with Unity:
var container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();
and then have the correct ILog logger instance passed in:
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}
The extension can be found here:
https://github.com/roblevine/UnityLoggingExtensions
More info here: http://blog.roblevine.co.uk/net/using-log4net-with-unity/
EDIT this is now available as a NuGet package
After hours of digging around in the Unity source code, I came up with the following solution. However, I would prefer to find a way to set the appropriate dependency resolver based on the type being resolved rather than overriding the default constructor selector policy. For one, because I previously overrode the default constructor selector for other purposes. For another, this solution only handles dependencies that are injected via constructor. For full coverage one would have to override the default property and method selectors as well I presume. For myself, I only need constructors.
class Logger_IOC_Tests
{
[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
container.AddNewExtension<LoggingExtension>();
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
class LoggingExtension : UnityContainerExtension
{
protected override void Initialize()
{
Context.Policies.SetDefault(typeof(IConstructorSelectorPolicy), new LoggingConstructorSelectorPolicy());
}
}
public class LoggingConstructorSelectorPolicy : DefaultUnityConstructorSelectorPolicy
{
protected override IDependencyResolverPolicy CreateResolver(ParameterInfo parameter)
{
return parameter.ParameterType == typeof(ILogger)
? new LoggerResolverPolicy(parameter.Member.DeclaringType)
: base.CreateResolver(parameter);
}
}
class LoggerResolverPolicy : IDependencyResolverPolicy
{
private readonly Type _dependantType;
public LoggerResolverPolicy(Type dependantType)
{
_dependantType = dependantType;
}
public object Resolve(IBuilderContext context)
{
return new Logger(_dependantType);
}
}
The above extension works well but more configuration information is needed for MVC5 users. Here are the steps using unity.
Add the following line to the top of your startup.cs class above the namespace.
[assembly: log4net.Config.XmlConfigurator(ConfigFile ="Web.config", Watch = true)]
In your global.asax application_startup method add the following information:
log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));
The rest of the configuration to the unity container should be as is:
container.AddNewExtension<Log4NetExtension>();
Ensure you have an appender added to your web.config. That should be about it to get this working correctly. Good Luck
With Unity 5 and above, you can now use Unity's own Log4Net extension from https://github.com/unitycontainer/log4net.
All you have to do is install the Nuget and add the extension to your container:
container.AddNewExtension<Log4NetExtension>();
And it will work automatically with any classes that use ILog as a dependency.
You can use the following code to inject Log4Net
log4net.Config.BasicConfigurator.Configure();
container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));
typeof(Program) is used since I'm registering in program class. Use can use the class name or this keyword
Then you can inject ILog into the class
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}

Categories

Resources