Is it possible in the .NET Moles framework to use the Fallthrough Behavior in Stub Types as we do with Mole Types?
I can override the default behavior of a Mole instance by doing:
MMyInstance.InstanceBehavior = MoleBehaviors.Fallthrough;
However for a Stub Instance i canĀ“t find in the BehavedBehaviors class the corresponding behavior.
I'm using version 0.94
Thanks
Hugo Pais
It is explained in the manual at "Partial Stubs". What you want is CallBase, which is a property of Stubs of Moles :
var stub = new SMyInstance() {CallBase = true};
or
stub.CallBase = true;
Hope this help.
Related
We're refactoring an older system to use DI. Sadly, some of the "core" components that are used all over everywhere have injection unfriendly constructors (descriptions, for example), so we have to use ServiceLocator to create them. Refactoring them is very impractical at this time.
We're trying to create the unfriendly classes by injecting ILifetimeScope into the appropriate place, but are getting the following exception:
No constructors on type 'Autofac.Core.Registration.ScopeRestrictedRegistry' can be found with the constructor finder 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'.
If I cheat and use the "Update" method on the ContainerBuilder and then register the container as the LifetimeScope, the resolution works successfully, however, given that Update is obsolete, it's not something I want to do.
Can anyone help?
Edit: I'm not doing anything special. Build up is standard:
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces();
this.Container = builder.Build();
builder = new ContainerBuilder();
builder.RegisterInstance(this.Container);
builder.RegisterInstance(this.Container).As<ILifetimeScope>();
builder.Update(this.Container);
Without these lines
builder = new ContainerBuilder();
builder.RegisterInstance(this.Container);
builder.RegisterInstance(this.Container).As<ILifetimeScope>();
builder.Update(this.Container);
any class with an ILifetimeScope dependency fails with the error above.
public class MyClass : IMyClass
{
public MyClass(ILifetimeScope scope)
{
...
}
}
I'm actually thinking that this is a bug in the Autofac Framework, so I'm hoping that someone from the team will be able to tell me more.
ILifetimeScope is supposed to automatically be available.
I have the following class, which uses constructor injection:
public class Service : IService
{
public Service(IRepository repository, IProvider provider) { ... }
}
For most methods in this class, I simply create Moq mocks for IRepository and IProvider and construct the Service. However, there is one method in the class that calls several other methods in the same class. For testing this method, instead of testing all those methods together, I want to test that the method calls those methods correctly and processes their return values correctly.
The best way to do this is to mock Service. I've mocked concrete classes with Moq before without issue. I've even mocked concrete classes that require constructor arguments with Moq without issue. However, this is the first time I've needed to pass mocked arguments into the constructor for a mocked object. Naturally, I tried to do it this way:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
However, that does not work. Instead, I get the following error:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: My.Namespace.Service.
Could not find a constructor that would match given arguments:
Castle.Proxies.IRepository
Castle.Proxies.IProvider
This works fine if Service's constructor takes simple arguments like ints and strings, but not if it takes interfaces that I'm mocking. How do you do this?
Why are you mocking the service you are testing? If you are wishing to test the implementation of the Service class (whether that be calls to mocked objects or not), all you need are mocks for the two interfaces, not the test class.
Instead of:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
Shouldn't it be this instead?
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Service(repository.Object, provider.Object);
I realize that it is possible to mock concrete objects in some frameworks, but what is your intended purpose? The idea behind mocking something is to remove the actual implementation so that it does not influence your test. But in your question, you have stated that you wish to know that certain classes are called on properly, and then you wish to validate the results of those actions. That is undoubtedly testing the implementation, and for that reason, I am having a hard time seeing the goals of mocking the concrete object.
I had a very similar problem when my equivalent of Service had an internal constructor, so it was not visible to Moq.
I added
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
to my AssemblyInfo.cs file for the implementing project. Not sure if it is relevant, but I wanted to add a suggestion on the off chance that it helps you or someone else.
It must be old version issue, all is ok with latest version. Nick, Please check!
P.s.: I started bounty by misstake (I had wrong signature in my constructor).
**I'm using PostSharp Express... not sure that would make a difference in this instance though.
I've got an OnMethodBoundary->OnEntry aspect that successfully multicasts at the assembly level to class members in my own code, but when I attempt to apply it to mscorlib System.IO.StreamReader members, no dice. Based on the searching I've done on the PostSharp web site, here on SO, and on Google, I can't tell what the correct way to go about this is with the current version of PostSharp. Does anyone know? Hopefully I'm just missing something simple :\
Here's the aspect followed by multicast attribute I'm using:
namespace Test.Aspects {
[AttributeUsage(AttributeTargets.Assembly)]
[MulticastAttributeUsage(MulticastTargets.Method, AllowMultiple = false)]
[Serializable]
public class PatchStreamReaderAttribute : OnMethodBoundaryAspect {
public override void OnEntry(MethodExecutionArgs args) {
System.Threading.Thread.Sleep(1000);
}
}
}
[assembly: PatchStreamReader(AttributeTargetMembers = "ReadLine", AttributeTargetAssemblies = "mscorlib", AttributeTargetTypes = "System.IO.StreamReader")]
Usually, when you apply an aspect in a given assembly, PostSharp will modify that assembly during its build process. This, of course, cannot happen for mscorlib or, in fact, for any 3-rd party library you reference but do not build from source code.
This is why PostSharp uses different approach when applying aspects to the referenced assemblies using AttributeTargetAssemblies. Instead of modifying the target 3-rd party assembly, PostSharp will modify the calls from your assembly to the target assembly.
This, of course, gives you less options of where you can inject your code. For example, PostSharp can detect the call to the library's method and inject the aspect around that call. But you cannot inject the aspect around the static or instance constructor of the type from the library.
You also need to pay attention to the AttributeTargetTypes property when applying the aspect. For example, you want to apply the aspect on the calls to the StreamReader.ReadLine() method. This virtual ReadLine() method is originally declared on the TextReader class and StreamReader overrides the method. If you look at the IL, then the method call looks like this:
callvirt instance string [mscorlib]System.IO.TextReader::ReadLine()
This means you need to set AttributeTargetTypes property to "System.IO.TextReader" to apply the aspect to the ReadLine() method.
I'm new to Pex and Moles and i want to make use of parametrized unit tests. I am using constructor injection and I want to create a moles stub for my parameter.
public UserLogic(IUserRepository userRepository)
{
_userRepository = userRepository;
}
The documentation Ive read says Moles will generate a stub type for my repository of SIUserRepository. But I cant figure out how to generate the stub. Would anyone be able to provide an example. Thanks
I'll assume you haven't gotten as far as creating a Moles assembly yet. Here's some basic steps to follow;
in your unit test project, expand the references, and right-click the assembly which contains the type IUserRepository - select 'Add Moles Assembly';
you'll now have Moles stubs & moles available for that assembly, under a '.Moles' namespace, so if you had MyAsssembly.SomeNamespace.IUserRepository, you'll now have a stub type available as MyAssembly.SomeNameSpace.Moles.SUserRepository
Now, in some UserLogic_Test method, you can refer to the stub like so;
[TestMethod]
public void UserLogic_Test()
{
MyAssembly.SomeNameSpace.Moles.SUserRepository mock = new SUserRepository();
UserLogic o = new UserLogic(mock);
Assert.AreEqual(1, o.SomeMethod());
}
I'm adding autofac to an existing project and some of the service implementations require their Initialize method to be called and passed configuration information. Currently I'm using the code:
builder.Register(context =>
{
var service =
new SqlTaxRateProvider(context.Resolve<IUserProvider>());
service.Initialize(config);
return service;
}
).As<ITaxService>()
.SingleInstance();
which works but I'm still creating the object myself which is what I'm trying to get away from this and allow autofac to handle it for me. Is it possible to configure a post create operation that would carry out the custom initialisation?
To give you an idea of what I'm after ideally this would be the code:
builder.RegisterType<SqlTaxRateProvider>()
.As<ITaxService>()
.OnCreated(service=> service.Initialize(config))
.SingleInstance();
Update:
I am using Autofac-2.1.10.754-NET35
.OnActivating(e => e.Instance.Initialize(...))
should do the trick.
You might also investigate the Startable module (see the Startable entry in the Autofac wiki).
Mark's suggestion to do initialisation in the constructor is also a good one. In that case use
.WithParameter(new NamedParameter("config", config))
to merge the config parameter in with the other constructor dependencies.