Using NInject to find a class, but constructing the class with your own parameters - ninject

I know this is not good practice.
Here is some code that sort of demonstrates the problem (but doesn't actually work):
public interface IBar {}
public interface Bar : IBar {}
public interface IFoo {}
public class Foo : IFoo
{
public Foo(IBar bar)
{
}
}
public class InjectionModule : NinjectModule
{
public override void Load()
{
Bind<IFoo>().To<Foo>();
}
}
public class MyApp
{
public void DoSomething()
{
// Get a foo with a particular bar
var foo1 = Kernel.Get<IFoo>(new Bar());
// Get another foo with a different bar
var foo2 = Kernel.Get<IFoo>(new Bar());
}
}
So what I am trying to do is to use NInject to bind IFoo to Foo, but have my app supply the Bar argument to the constructor at runtime, rather than the usual practice where NInject resolves the IBar dependency.

var foo1 = Kernel.Get<IFoo>(new ConstructorArgument("bar", new Bar()));

Related

Moq class with constructors ILogger and options netcore 2.1 vs2017 getting error

I need to mock a class that has parameters in the constructor by I cannot figure out how you do it using moq. It crashes
Constructor arguments cannot be passed for interface mocks.
See my attempt below:
[Fact]
public async Task MyTest()
{
var mySettings= GetMySettings();
var mySettingsOptions = Options.Create(mySettings);
var mockLogger = Mock.Of<ILogger<MyClass>>();
var mock=new Mock<IMyClass>(mySettings,mockLogger);
mock.Setup(x=>x.DoSomething(It.IsAny<string>().Returns("todo");
}
public class MyClass : IMyClass
{
private readonly ILogger<MyClass> logger;
private readonly MySettings mySettings;
public MyClass(IOptions<MySettings> settings,ILogger<MyClass>logger)
{
this.logger = logger;
this.mySettings = settings.Value;
}
public string DoSomething(string myarg)
{
//omitted
}
}
How do you do it? many thanks
EDITED
In order to mock repository and test the behaviour i also need to mock the other classes that have constructors in it. Hope makes sense
public class MyService:IMyService
{
private MyClass myclass;
private OtherClass otherClass;
private Repository repository;
public MyService(IRepository repository,IMyClass myclass,IMyOtherClass otherClass)
{
this.myclass=myClass;
this.otherClass=otherClass;
this.repository=repository;
}
public void DoStuff()
{
bool valid1=myclass.Validate(); //mock myclass
var valid2=otherClass.Validate(); //mock otherClass
if(Valid1 && valid2)
{
repository.GetSomething();//this is really what I am mocking
}
//etc..
}
}
It doesn't matter if your class constructor has parameters or not, because you're working with its mock object.
var mock = new Mock<IMyClass>();
mock.Setup(x=>x.DoSomething(It.IsAny<string>()).Returns("todo");
Then you can use this mock to your repository constructor:
var myService = new MyService(repositoryMock.Object, mock.Object, otherClassMock.Object);
You are getting this error because you are trying to create a mock of an interface (IMyClass in this case) with constructor values. It seems like you are trying to test the method in the class MyClass, therefore you should be creating a moq of this class.
To clarify change
var mock=new Mock<IMyClass>(mySettings,mockLogger); to var mock=new Mock<MyClass>(mySettings,mockLogger);

Why does ninject's constructorScorer rate constructors which have unresolvable params?

Given some simple classes and interfaces...
public interface IClass1 { }; public class Class1 : IClass1 { }
public interface IClass2 { }; public class Class2 : IClass2 { }
... this injectable code ...
public class Class3
{
public Class3(IClass1 class1, IClass2 class2)
{
}
public Class3(IClass1 class1)
{
}
}
... and this setup ...
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<IClass1>().To<Class1>();
var instance = kernel.Get<IClass1>();
}
Ninject will crash declaring that it can't find a binding for IClass2.
On the one had this is understandable, because it doesn't have a binding for IClass2.
However it does have access to a constructor which does not require such a binding.
After some investigation, we have discovered that both of these constructors have the same 'score' because they both have the same number of resolvable parameters.
Ninject appears to treat them as equally valid. It picks the constructor which requires an IClass2 parameter because it is listed first within the code.
So if I reverse the order of these constructors thus...
public class Class3
{
public Class3(IClass1 class1)
{
}
public Class3(IClass1 class1, IClass2 class2)
{
}
}
... everything works.
My question is therefore....
Why is the constructor (the one requiring an IClass2 parameter) ever considered a valid contender when it has unresolvable parameters?

check that property setter was called

I have a class I am unit testing and all I want to do is to verify that the public setter gets called on the property. Any ideas on how to do this?
I don't want to check that a value was set to prove that it was called. I only want to ensure that the constructor is using the public setter . Note that this property data type is a primitive string
This is not the sort of scenario that mocking is designed for because you are trying to test an implementation detail. Now if this property was on a different class that the original class accessed via an interface, you would mock that interface and set an expectation with the IgnoreArguments syntax:
public interface IMyInterface
{
string MyString { get; set; }
}
public class MyClass
{
public MyClass(IMyInterface argument)
{
argument.MyString = "foo";
}
}
[TestClass]
public class Tests
{
[TestMethod]
public void Test()
{
var mock = MockRepository.GenerateMock<IMyInterface>();
mock.Expect(m => m.MyString = "anything").IgnoreArguments();
new MyClass(mock);
mock.VerifyAllExpectations();
}
}
There are 2 problems with what you are trying to do. The first is that you are trying to mock a concrete class, so you can only set expectations if the properties are virtual.
The second problem is the fact that the event that you want to test occurs in the constructor, and therefore occurs when you create the mock, and so occurs before you can set any expectations.
If the class is not sealed, and the property is virtual, you can test this without mocks by creating your own derived class to test with such as this:
public class RealClass
{
public virtual string RealString { get; set; }
public RealClass()
{
RealString = "blah";
}
}
[TestClass]
public class Tests
{
private class MockClass : RealClass
{
public bool WasStringSet;
public override string RealString
{
set { WasStringSet = true; }
}
}
[TestMethod]
public void Test()
{
MockClass mockClass = new MockClass();
Assert.IsTrue(mockClass.WasStringSet);
}
}

Castle windsor wire generic irepository with 2 types

Hi I am trying to change a code example found here
http://imar.spaanjaars.com/577/aspnet-n-layered-applications-implementing-a-repository-using-ef-code-first-part-5
In his example he uses structure map, when I converted it to windsor I can get it to work with the one repository using the following.
container.Register(Component.For<IUnitOfWorkFactory>().ImplementedBy<EFUnitOfWorkFactory>(),
Component.For<IUnitOfWork>().ImplementedBy<EFUnitOfWork>(),
Component.For<Model.Repositories.IPeopleRepository>().ImplementedBy<PeopleRepository>().LifestyleTransient());
But what I really want to do is to map all the irepository based interfacees to thier implementation.
Here is the IRepository, T is the entity, K is the prmiary key type
public interface IRepository<T, K> where T : class
{
}
Its implementation Is
public abstract class Repository<T> : IRepository<T, int>, IDisposable where T : DomainEntity<int>
{
}
My controller has the interface IPeopleRepository as a constructor paramerter.
public interface IPeopleRepository : IRepository<Person, int>
{
}
public class PeopleRepository : Repository<Person>, IPeopleRepository
{
}
I want to have one register to register all repositories, something like this, but it wont match and i get the error Service 'Spaanjaars.ContactManager45.Model.Repositories.IPeopleRepository' which was not registered
container.Register(Component.For(typeof(IRepository<,>))
.ImplementedBy(typeof(Repository<>))
.LifestylePerWebRequest());
What am i missing in regards to this? is it because my irepository has 2 generic types?
In order to map all the IRepository based interfaces to their implementations .WithService.AllInterfaces() should be used.
This registration should solve your issue.
container.Register(
Classes.FromThisAssembly()
.BasedOn(typeof(IRepository<,>))
.WithService.AllInterfaces()
.LifestylePerWebRequest());
There are some tests to test it. I claim they are green.
[TestClass]
public class InstallerTest
{
private IWindsorContainer container;
[TestInitialize]
public void Init()
{
container = new WindsorContainer().Install(new Installer());
}
[TestMethod]
public void ResilveTest_ResolvesViaIRepository()
{
// act
var repository = container.Resolve<IRepository<Person, int>>();
// assert
repository.Should().BeOfType<PeopleRepository>();
}
[TestMethod]
public void ResilveTest_ResolvesViaIPeopleRepository()
{
// act
var repository = container.Resolve<IPeopleRepository>();
// assert
repository.Should().BeOfType<PeopleRepository>();
}
}
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Classes.FromThisAssembly()
.BasedOn(typeof(IRepository<,>))
.WithService.AllInterfaces()
.LifestylePerThread());
}
}

Ninject bind all factory interfaces

Is there a simple way to use Ninject to bind all Factory interfaces to the ToFactory() extention method?
public class Foo
{
readonly IBarFactory barFactory;
public Foo(IBarFactory barFactory)
{
this.barFactory = barFactory;
}
public void Do()
{
var bar = this.barFactory.CreateBar();
...
}
}
public interface IBarFactory
{
Bar CreateBar();
}
For the code above I could use:
kernel.Bind<IBarFactory>().ToFactory();
What would I do though if I had 10 or 20 IFactory interfaces that needed binding?
Yes use conventions: https://github.com/ninject/ninject.extensions.conventions
this.Bind(x => x.From_UseSomeOverloadToSpecifyTheAssemblies()
.SelectAllInterfaces().EndingWith("Factory")
.BindToFactory();