NSubstitute: Arg.Do does not fulfill the list of called parameters - nsubstitute

For the code bellow I get this assert failure and do not know why:
Assert.AreEqual failed. Expected:<2>. Actual:<0>.
public interface IA
{
void MethodA(B b);
}
public class A : IA
{
public void MethodA(B b) {/*no matter*/}
}
public class B
{
public string PropertyB { get; set; }
}
public class MyLogic
{
private IA _a;
public MyLogic(IA a)
{
_a = a;
}
public void DoLogic()
{
_a.MethodA(new B { PropertyB = "first" });
_a.MethodA(new B { PropertyB = "second" });
}
}
[TestClass]
public class MyLogicTests
{
[TestMethod]
public void CallTwiceAndCheckTheParams()
{
List<B> args = new List<B>();
IA a = Substitute.For<IA>();
new MyLogic(a).DoLogic();
a.Received(2).MethodA(Arg.Do<B>(x => args.Add(x)));
Assert.AreEqual(2, args.Count);
}
}

The code is setting up an action to perform (Arg.Do) after the calls have already been made. I think this is what you are after:
List<B> args = new List<B>();
IA a = Substitute.For<IA>();
a.MethodA(Arg.Do<B>(x => args.Add(x))); // do this whenever MethodA is called
new MyLogic(a).DoLogic();
a.Received(2).MethodA(Arg.Any<B>());
Assert.AreEqual(2, args.Count);

Related

closed generic type registration - Autofac – cannot resolve parameter x of constructor

I am getting the following exception:
"None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository' can be invoked with the available services and parameters:\r\nCannot resolve parameter 'NetCore.DAL.EF.DatabaseFactory1[NetCore.DAL.EF.AppDbContext] databaseFactory' of constructor 'Void .ctor(NetCore.DAL.EF.DatabaseFactory1[NetCore.DAL.EF.AppDbContext])'."
Here is the Autofac registration info for SystemSettingRepository:
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28] = {Activator = SystemSettingRepository (ReflectionActivator), Services = [Dcs.NetCore.ApplicationCore.BLL.Domain.Features.Common.SystemSettings.ISystemSettingRepository, Dcs.NetCore.Infrastructure.Common.IRepository`1[[Dcs.NetCore.ApplicationCore.BLL.Domain.Entities.Common.SystemSetting, Dcs.NetCore.ApplicationCore.BLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope}
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28].Target.Services[0].ServiceType = {Dcs.NetCore.ApplicationCore.BLL.Domain.Features.Common.SystemSettings.ISystemSettingRepository}
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28].Target.Services[1].ServiceType = {Dcs.NetCore.Infrastructure.Common.IRepository`1[Dcs.NetCore.ApplicationCore.BLL.Domain.Entities.Common.SystemSetting]}
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28].Target.Services[2].ServiceType = {NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository}
As you can see, the services are registered. However, the databaseFactory parameter is not. Here is my code:
public class Startup
{
…
public IServiceProvider ConfigureServices(IServiceCollection services)
{
…
return AutofacBuilder();
}
private AutofacServiceProvider AutofacBuilder()
{
var builder = new ContainerBuilder();
builder.RegisterModule<AutofacModule_AspNetCore>();
builder.Populate(_services);
this.AutofacContainer = builder.Build();
var autofacServiceProvider = new AutofacServiceProvider(this.AutofacContainer);
return autofacServiceProvider;
}
}
public class AutofacModule_AspNetCore : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
RegisterDbContexts();
RegisterComponents();
}
private void RegisterComponents()
{
_builder.RegisterGeneric(typeof(DatabaseFactory<>))
.As(typeof(IDatabaseFactory<>))
.InstancePerDependency();
_builder.RegisterAssemblyTypes(_assembly)
.AsClosedTypesOf(typeof(IRepository<>))
.WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
(p, i) => i.Resolve<DatabaseFactory<AppDbContext>>()))
//.WithParameter("databaseFactory", new DatabaseFactory<AppDbContext>())
//.WithParameter(ResolvedParameter//.ForNamed<IDbContext>("coreDomainDbContext"));
//.WithParameter("databaseFactory", )
.InstancePerDependency();
}
private void RegisterDbContexts()
{
RegisterAppDbContextInstance();
}
private void RegisterAppDbContextInstance()
{
// register DbContextOptionsBuilderHelper
_builder.RegisterType<AppDbContextOptionsBuilderHelper>()
.InstancePerDependency();
// configure DbContextOptions
var dbContextOptionsBuilderHelper = new AppDbContextOptionsBuilderHelper();
var dbContextOptionsBuilder = dbContextOptionsBuilderHelper.GetDbContextOptionsBuilder();
// register DbContext
_builder.RegisterType<AppDbContext>()
.WithParameter("options", dbContextOptionsBuilder.Options)
.InstancePerDependency();
}
}
public class DatabaseFactory<T> : Disposable, IDatabaseFactory<T>
where T : DbContext //, new()
{
private T _dbContext;
private AppDbContextOptionsBuilderHelper _appDbContextOptionsBuilderHelper;
private DefaultDbContextOptionsBuilderHelper _defaultDbContextOptionsBuilderHelper;
public DatabaseFactory()
{
this._appDbContextOptionsBuilderHelper = new AppDbContextOptionsBuilderHelper(); // TODO: refactor to ctor injection
this._defaultDbContextOptionsBuilderHelper = new DefaultDbContextOptionsBuilderHelper(); // TODO: refactor to ctor injection
}
public T Get()
{
if (_dbContext == null)
Create();
return _dbContext;
}
private void Create()
{
switch (typeof(T).Name)
{
case "AppDbContext":
{
CreateAppDbContext();
break;
}
case "DefaultDbContext":
{
CreateDefaultDbContext();
break;
}
}
}
private void CreateAppDbContext()
{
var dbContextOptionsBuilder = _appDbContextOptionsBuilderHelper.GetDbContextOptionsBuilder();
this._dbContext = new AppDbContext(dbContextOptionsBuilder.Options) as T;
}
//protected override void DisposeCore()
//{
//
// cref: Autofac.Util.Disposable
//
// //TODO: should I override Autofac.Util.Disposable here?
// var msg = "DatabaseFactory.DisposeCore() executing";
// if (_dbContext != null)
// _dbContext.Dispose();
//}
}
public partial class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{ }
public AppDbContext()
{}
}
public class SystemSettingRepository : RepositoryBase<SystemSetting, AppDbContext>, ISystemSettingRepository
{
public SystemSettingRepository(DatabaseFactory<AppDbContext> databaseFactory)
: base(databaseFactory)
{ }
}
public interface ISystemSettingRepository : IRepository<SystemSetting>
{}
public partial interface IRepository<T> where T : class
{}
public abstract class RepositoryBase<T, U> : IRepositoryBase<T, U>
where T : class
where U : DbContext //, new()
{
private U _dbContext;
private readonly DbSet<T> _dbset;
protected RepositoryBase(DatabaseFactory<U> databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = DataContext.Set<T>();
}
protected virtual DatabaseFactory<U> DatabaseFactory
{
get;
private set;
}
protected virtual U DataContext
{
get { return _dbContext = DatabaseFactory.Get(); }
}
public virtual async Task<T> AddAsync(T dao)
{
EntityEntry<T> entityEntry = _dbset.Add(dao);
var result = await SaveChangesAsync();
if (result > 0 && entityEntry != null && entityEntry.Entity != null)
return entityEntry.Entity;
else
return null;
}
}
public interface IRepositoryBase<T, U>
where T : class
where U : DbContext //, new()
{ }
The issue is caused by the way of registration of DatabaseFactory<>. This type is registered as an interface IDatabaseFactory<>. But it is resolved as itself in lambda argument of method WithParameter() on registration of repositories:
_builder.RegisterAssemblyTypes(_assembly)
.AsClosedTypesOf(typeof(IRepository<>))
.WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
// resolving type it self
// while it was registered as interface
(p, i) => i.Resolve<DatabaseFactory<AppDbContext>>()))
Autofac doesn't know how to resolve it, because it doesn't have corresponding registration. To make your code work you can resolve DatabaseFactory as an inteface like this:
.WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
(p, i) => i.Resolve<IDatabaseFactory<AppDbContext>>()))
Or add AsSelf() call to registration:
_builder.RegisterGeneric(typeof(DatabaseFactory<>))
.As(typeof(IDatabaseFactory<>))
// Register also as DatabaseFactory<>
.AsSelf()
.InstancePerDependency();

Trouble mocking a private method

So, I am having an issue mocking a private method. From everything I have seen it should work, but isn't.
Let's start with the basics - Here is the code under test
public sealed class UnderTest
{
private bool MockPrivate(string name)
{
[snip]
}
private string MethodUnderTest(ParameterHolder parameters)
{
if (!this.MockPrivate(parameters.Parameter2))
{
return null;
}
[Snip]
}
[Snip]
}
public sealed class ParameterHolder
{
public ParameterHolder (bool parameter1, string parameter2)
{
this.Parameter1 = parameter1;
this.Parameter2 = parameter2;
}
public bool Parameter1
{
get;
private set;
}
public string Parameter2
{
get;
private set;
}
}
Here is the test method
public void Test_UnderTest_MethodUnderTest()
{
UnderTest testClass;
ParameterHolder parameters;
dynamic h;
testClass = new UnderTest();
parameters = Isolate.Fake.Instance<ParameterHolder>(Members.CallOriginal);
Isolate.WhenCalled(() => parameters.Parameter1).WillReturn(true);
Isolate.WhenCalled(() => parameters.Parameter2).WillReturn("parameter2value");
h = testClass.AsDynamic();
Isolate.WhenCalled(() => h.MockPrivate((string)null)).WillReturn(true);
Assert.IsNotNull(h.MethodUnderTest(parameters));
}
I have also tried to change the isolate call to:
Isolate.WhenCalled(() => h.MockPrivate("parameter2value").WillReturn(true);
and
Isolate.WhenCalled(() => h.MockPrivate(parameters.Parameter2).WillReturn(true);
In all the cases, the MockPrivate method gets executed, instead of returning the mocked True value.
Any help would be appreciated.
Ok, did some more checking and this is the correct way:
Isolate.NonPublic.WhenCalled(testClass, "MockPrivate").WillReturn(true);

NInject kernel GetAll returns empty

I've two projects (class library projects) which implement one interface:
The first one:
public class MailPlugin : Extensibility.IProductorPlugin
{
...
}
The second one:
public class FileSystemPlugin : Extensibility.IProductorPlugin
{
...
}
Extensibility.IProductorPlugin, is a interface of a third project:
namespace Extensibility
{
public delegate void NotifyDigitalInputs(List<Domain.DigitalInput> digital_inputs);
public interface IProductorPlugin
{
String Name { get; }
String Description { get; }
String Version { get; }
List<Domain.Channel> AvailableChannels { get; }
IEnumerable<Guid> TypeGuids { get; }
event NotifyDigitalInputs OnDigitalInputs;
}
}
In my composition root, I've created this class:
namespace UI
{
public sealed class NinjectServiceLocator
{
private static readonly Lazy<NinjectServiceLocator> lazy = new Lazy<NinjectServiceLocator>(() => new NinjectServiceLocator());
public static NinjectServiceLocator Instance { get { return lazy.Value; } }
public Ninject.IKernel Kernel { get; private set; }
private NinjectServiceLocator()
{
using (var k = this.Kernel = new Ninject.StandardKernel())
{
k.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(Extensibility.IProductorPlugin))
.BindAllInterfaces()
);
}
}
}
}
So, when I want to look for all plugins, I just perform this:
protected void initialize()
{
foreach (Extensibility.IProductorPlugin productor_plugin in NinjectServiceLocator.Instance.Kernel.GetAll(typeof(Extensibility.IProductorPlugin)))
{
using (var channel_tile = new DevExpress.XtraBars.Docking2010.Views.WindowsUI.Tile() { Group = "Plugin Channels" })
{
foreach (Domain.Channel channel in productor_plugin.AvailableChannels)
{
channel_tile.Elements.Add(new DevExpress.XtraEditors.TileItemElement() { Text = channel.Name });
channel_tile.Elements.Add(new DevExpress.XtraEditors.TileItemElement() { Text = channel.Description });
this.tileContainer1.Items.Add(channel_tile);
}
}
}
}
However, GetAll returns anything.
What am I doing wrong?
I'll appreciate a lot your help.
Thanks for all.
try removing the using() from around the Kernel instantiation. a using will dispose the object at the end of the scope, which we don't want for a kernel.
using (var k = this.Kernel = new Ninject.StandardKernel())

orika property expression mapping

Given
classA {
long fahr;
....
and
classB {
long cels;
....
how can I map the following in Orika?
A.fahr <-> (B.cels*9)/5
Do I need customised Mapper or Filter ?
I suggest to use field level converter if both are of different data types but since they are of same data type we have to use a custom converter for entire class.
This is sample converter that suitable for this use case.
import ma.glasnost.orika.BoundMapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.converter.ConverterFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
public class EntryClass {
public static void main(String[] args) {
EntryClass ec = new EntryClass();
BoundMapperFacade<A, B> facade = getMapperFactory().getMapperFacade(A.class, B.class);
A fahr = new A(455);
B cels = facade.map(fahr);
System.out.println(cels);
A revFahr = facade.mapReverse(cels);
System.out.println(revFahr);
}
private static MapperFactory getMapperFactory() {
MapperFactory factory = new DefaultMapperFactory.Builder()
.build();
ConverterFactory cfactory = factory.getConverterFactory();
cfactory.registerConverter(new FahrCelsConverter());
factory.classMap(A.class, B.class)
.field("fahr", "cels")
.byDefault()
.register();
return factory;
}
}
public class A {
long fahr;
public A(long fahr) {
this.fahr = fahr;
}
public long getFahr() {
return fahr;
}
public void setFahr(long fahr) {
this.fahr = fahr;
}
#Override
public String toString() {
return "A [fahr=" + fahr + "]";
}
}
public class B {
long cels;
public B(long cels) {
this.cels = cels;
}
public long getCels() {
return cels;
}
public void setCels(long cels) {
this.cels = cels;
}
#Override
public String toString() {
return "B [cels=" + cels + "]";
}
}
public class FahrCelsConverter extends BidirectionalConverter<A, B>
{
#Override
public B convertTo(A source, Type<B> destinationType, MappingContext mappingContext) {
if(source != null)
{
return new B((source.fahr - 32) * 5 / 9);
}
return null;
}
#Override
public A convertFrom(B source, Type<A> destinationType, MappingContext mappingContext) {
if(source != null)
{
return new A((source.cels / 5) * 9 + 32);
}
return null;
}
}
It's more suited to use a converter (by id).

Ninject Intercept any method with certain attribute?

How can I get Ninject.Extensions.Interception to basically let me bind a specific interceptor to any method that has an attribute... psudocode:
Kernel.Intercept(context => context.Binding.HasAttribute<TransactionAttribute>())
.With<TransactionInterceptor>
With a class like:
public SomeClass
{
[TransactionAttribute]
public void SomeTransactedMethod()
{ /*do stuff */ }
}
Assuming that you are using Ninject.Extensions.Interception this should do the trick
public class TransactionInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// Do something...
}
}
public class TransactionAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return new TransactionInterceptor();
}
}
public class SomeClass
{
[Transaction]
public virtual void SomeTransactedMethod() { }
}
Make sure that the method that should be intercepted is marked as virtual.
When SomeTransactedMethod() is called it should be intercepted.
var kernel = new StandardKernel();
kernel.Bind<SomeClass>().ToSelf();
var someClass = kernel.Get<SomeClass>();
someClass.SomeTransactedMethod();
UPDATE
You could create a custom planning strategy.
public class CustomPlanningStrategy<TAttribute, TInterceptor> :
NinjectComponent, IPlanningStrategy
where TAttribute : Attribute
where TInterceptor : IInterceptor
{
private readonly IAdviceFactory adviceFactory;
private readonly IAdviceRegistry adviceRegistry;
public CustomPlanningStrategy(
IAdviceFactory adviceFactory, IAdviceRegistry adviceRegistry)
{
this.adviceFactory = adviceFactory;
this.adviceRegistry = adviceRegistry;
}
public void Execute(IPlan plan)
{
var methods = GetCandidateMethods(plan.Type);
foreach (var method in methods)
{
var attributes = method.GetCustomAttributes(
typeof(TAttribute), true) as TAttribute[];
if (attributes.Length == 0)
{
continue;
}
var advice = adviceFactory.Create(method);
advice.Callback = request => request.Kernel.Get<TInterceptor>();
adviceRegistry.Register(advice);
if (!plan.Has<ProxyDirective>())
{
plan.Add(new ProxyDirective());
}
}
}
}
private static IEnumerable<MethodInfo> GetCandidateMethods(Type type)
{
var methods = type.GetMethods(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance
);
return methods.Where(ShouldIntercept);
}
private static bool ShouldIntercept(MethodInfo methodInfo)
{
return methodInfo.DeclaringType != typeof(object) &&
!methodInfo.IsPrivate &&
!methodInfo.IsFinal;
}
}
This should now work.
var kernel = new StandardKernel();
kernel.Components.Add<IPlanningStrategy,
CustomPlanningStrategy<TransactionAttribute, TransactionInterceptor>>();
kernel.Bind<SomeClass>().ToSelf();
var someClass = kernel.Get<SomeClass>();
someClass.SomeTransactedMethod();
Here is the code that I used for the same purpose
//Code in Bind Module
this.Bind(typeof(ServiceBase<,>))
.ToSelf()
.InRequestScope()
.Intercept()
.With<TransactionInterceptor>();
And
public class TransactionInterceptor : IInterceptor
{
#region Constants and Fields
public ISession session;
private ISessionFactory sessionFactory;
#endregion
#region Constructors and Destructors
public TransactionInterceptor(ISession session, ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
this.session = session;
}
#endregion
public void Intercept(IInvocation invocation)
{
try
{
if (!session.IsConnected)
session = sessionFactory.OpenSession();
session.BeginTransaction();
invocation.Proceed();
if (this.session == null)
{
return;
}
if (!this.session.Transaction.IsActive)
{
return;
}
else
{
this.session.Transaction.Commit();
}
}
catch (Exception)
{
if (this.session == null)
{
return;
}
if (!this.session.Transaction.IsActive)
{
return;
}
this.session.Transaction.Rollback();
throw;
}
}
}
And code for TransactionAttribute
public class TransactionAttribute : InterceptAttribute
{
#region Public Methods
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<TransactionInterceptor>() ;
}
#endregion
}