NSubstitute and Unity - c#

I am currently trying to learn DI & Mocking, with Unity and NSubstitute. I am also using an automocking extension taken from this question: Is this possible with Unity (Instead of Castle Windsor)?
In my unit test below I am trying to set an NSubstitute return value of 10 from my method Add(). However when debugging through the controller call the assigned value is the default 0 rather than the expected 10. The proxy does not seem to be intercepting the method call.
I suspect this is caused by not registering my Types/container correctly, anybody able to point me in the right direction?
[TestFixture]
public class ApplicationControllerTests
{
private IUnityContainer _container;
private ApplicationController _controller;
private ISampleService _sampleService;
[SetUp]
public void SetUp()
{
_container = new UnityContainer().AddExtension(new AutoMockingContainerExtension());
_controller = _container.Resolve<ApplicationController>();
_sampleService = _container.Resolve<ISampleService>();
}
[Test]
public void TestSampleService()
{
// This line is not working
_sampleService.Add(Arg.Any<int>(), Arg.Any<int>()).Returns(10);
var result = _controller.Index();
_sampleService.Received().Add(Arg.Any<int>(), Arg.Any<int>());
}
}
public class AutoMockingContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer _container;
public AutoMockingBuilderStrategy(IUnityContainer container)
{
_container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !_container.IsRegistered(key.Type))
context.Existing = CreateSubstitute(key.Type);
}
private static object CreateSubstitute(Type type)
{
return Substitute.For(new[] { type }, null);
}
}
}
And my controller code
public class ApplicationController : BaseController
{
private readonly ISampleService _sampleService;
public ApplicationController(ISampleService sampleService)
{
_sampleService = sampleService;
}
public ActionResult Index()
{
var result = _sampleService.Add(2, 3);
// result is 0, expected 10 ??
return View();
}
}
public interface ISampleService
{
int Add(int first, int second);
}
public class SampleService : ISampleService
{
public int Add(int first, int second)
{
return first + second;
}
}

Actually Tormod is right the problem is that the AutoMockingBuilderStrategy returns a different mock instance every time when somebody requests an ISampleService form the container.
So there is a bug in my original implementation namely the AutoMockingBuilderStrategy doesn't store the created mocks:
Here is a fixed version:
public class AutoMockingContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer container;
private readonly Dictionary<Type, object> substitutes
= new Dictionary<Type, object>();
public AutoMockingBuilderStrategy(IUnityContainer container)
{
this.container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !container.IsRegistered(key.Type))
{
context.Existing = GetOrCreateSubstitute(key.Type);
context.BuildComplete = true;
}
}
private object GetOrCreateSubstitute(Type type)
{
if (substitutes.ContainsKey(type))
return substitutes[type];
var substitute = Substitute.For(new[] {type}, null);
substitutes.Add(type, substitute);
return substitute;
}
}
}

I suspect that you are dealing with two different instances of ISampleService, created in lines 2 and 3 of Setup, respectively.
Could you, for test, make the _sampleServie field public and in the third Setup() line try
_sampleService = _controller._sampleService;

Related

using localization service GetAllLanguages from a component composer, incorrect DI?

I have an interface as below, which I use to add a specific language if it does not exist:
public interface IGetLanguagesService
{
void GetLanguages(ILocalizationService localization);
}
public class LanguageService : IGetLanguagesService
{
ILocalizationService _localizationService;
public void GetLanguages(ILocalizationService localization)
{
_localizationService = localization;
var currentLanguages = _localizationService.GetAllLanguages();
bool exists = false;
foreach (var currentLan in currentLanguages)
{
if (currentLan.IsoCode == "es-ES")
{
exists = true;
}
}
if (!exists)
{
AddLanguage(_localizationService);
}
}
public void AddLanguage(ILocalizationService localization)
{
var languageSE = new Language("es-ES") { CultureName = "es-ES", IsMandatory = true };
localization.Save(languageSE);
}
}
I want to use this at start-up so have created a component composer, which on Initialize() I want to call CallGetLanguages() but Im not entirely sure what should be in Initialize(), I think my DI may be wrong?
public class LanguagesComposer : ComponentComposer<LanguagesComponent>
{
public void Compose(Composition composition)
{
composition.Register<IGetLanguagesService>(Lifetime.Singleton);
composition.Register<ILocalizationService>(Lifetime.Singleton);
composition.Components().Append<LanguagesComponent>();
}
}
public class LanguagesComponent : IComponent
{
public void Initialize()
{
???????
}
public void Terminate()
{
throw new NotImplementedException();
}
IGetLanguagesService _getLanguagesService;
ILocalizationService _localization;
public void CallGetLanguages(IGetLanguagesService getLanguages, ILocalizationService localization)
{
_getLanguagesService = getLanguages;
_localization = localization;
_getLanguagesService.GetLanguages(localization);
}
}
You've passed ILocalizationService localization instance to LanguageService twice, pass it to constructor instead and use a constructor injection. The same issue with LanguagesComponent, pass all its dependencies to constructor instead of methods

Can you have generic create method for Zenject

So I have a base class and some derived classes, I want to have just one factory with generic create method witch will create appropriate instances and inject all dependencies. Is this possible using Zenject?
Something like.
factory.Create<Archer>()
For now I am doing this but as you see this is not very clean solution.
public class CustomFactory : IFactory<Type, BaseUnit>
{
private DiContainer _container;
public CustomFactory(DiContainer container)
{
_container = container;
}
public BaseUnit Create<Type>()
{
return null;
}
public BaseUnit Create(Type type)
{
if (type.BaseType != typeof(BaseUnit))
{
Debug.LogError("you cant create objects that are not derrived from base unit");
return null;
}
object obj = _container.Resolve(type) ;
return _container.InstantiatePrefabForComponent(type, obj as UnityEngine.Object, null, new object[0]) as BaseUnit;
}
}
I think the way you have it is probably the easiest way to do this. Here's some minor changes to what you did:
public class UnitFactory
{
readonly DiContainer _container;
readonly List<UnityEngine.Object> _prefabs;
public UnitFactory(
List<UnityEngine.Object> prefabs,
DiContainer container)
{
_container = container;
_prefabs = prefabs;
}
public BaseUnit Create<T>()
where T : BaseUnit
{
var prefab = _prefabs.OfType<T>().Single();
return _container.InstantiatePrefabForComponent<T>(prefab);
}
}
public class TestInstaller : MonoInstaller<TestInstaller>
{
public FooUnit FooPrefab;
public BarUnit BarPrefab;
public override void InstallBindings()
{
Container.Bind<UnitFactory>().AsSingle();
Container.Bind<UnityEngine.Object>().FromInstance(FooPrefab).WhenInjectedInto<UnitFactory>();
Container.Bind<UnityEngine.Object>().FromInstance(BarPrefab).WhenInjectedInto<UnitFactory>();
}
}
Only drawback with this approach is that the prefabs will not be validated, so if they have missing injections it won't be caught until runtime. The alternative would be to create individual factories for each BaseUnit, and then inject those factories into UnitFactory, but that would probably get messy

Retrieve instantiated types from UnityContainer

(Using Unity 4.0.1)
Given a UnityContainer object, is there any way to retrieve all the objects that have been instantiated by the container up to that point in time? E.g. something like
IEnumerable<object> instantiatedObjects = unityContainer.GetAllInstantiatedObjects();
or, even better, filtering according to those that derive from a given type:
IEnumerable<IFoo> instantiatedFoos = unityContainer.GetAllInstantiatedObjects<IFoo>();
Following RB's suggestion, the following approach implements a custom Unity extension with a strategy that keeps a reference to each instantiated object upon PostInitializtion.
N.B. The following code is for illustration only, and is not intended to be thread-safe/exception-safe etc.
First, the implementation of the Extension class and other classes it relies on.
public class ObjectContainer
{
private readonly List<object> _instantiatedObjects = new List<object>();
public void Add(object instantiatedObject)
{
_instantiatedObjects.Add(instantiatedObject);
}
public IEnumerable<object> GetInstantiatedObjects()
{
return _instantiatedObjects;
}
public IEnumerable<T> GetInstantiatedObjects<T>()
{
return GetInstantiatedObjects().OfType<T>();
}
}
public class InstantiatedObjectsStrategy : BuilderStrategy
{
private readonly ObjectContainer _objectContainer;
public InstantiatedObjectsStrategy(ObjectContainer objectContainer)
{
_objectContainer = objectContainer;
}
public override void PostBuildUp(IBuilderContext context)
{
_objectContainer.Add(context.Existing);
}
}
public class InstantiatedObjectsExtension : UnityContainerExtension
{
private readonly ObjectContainer _objectContainer = new ObjectContainer();
protected override void Initialize()
{
Context.Container.RegisterInstance(_objectContainer);
Context.Strategies.Add(new InstantiatedObjectsStrategy(_objectContainer),
UnityBuildStage.PostInitialization);
}
}
The extension can be added to the UnityContainer immediately after creation:
IUnityContainer container = new UnityContainer();
container.AddNewExtension<InstantiatedObjectsExtension>();
The instantiated objects can then be retrieved from the container at a later stage as follows:
IEnumerable<object> instantiatedObjects = container.Resolve<ObjectContainer>().GetInstantiatedObjects();
IEnumerable<Foo> instantiatedFoos = container.Resolve<ObjectContainer>().GetInstantiatedObjects<Foo>();

Compare Action<T>

I have a service class as below:
public class MyService
{
private readonly IMyDependency _myDependency;
public MyService(IMyDependency myDependency)
{
_myDependency = myDependency;
}
public void MyHandler(string param)
{
// work
}
public void AnotherMethod()
{
_myDependency.DoWork(MyHandler);
}
}
How can I Unit Test that MyHandler has been given as a parameter of DoWork()?
Since you are using Moq, you can write test like this:
[TestMethod]
public void DoWorkWasCalledWithCorrectParameters()
{
var mock = new Moq.Mock<IMyDependency>();
var myService = new MyService(mock.Object);
myService.AnotherMethod();
// verify that method was called once and with correct parameter:
mock.Verify(x => x.DoWork(myService.MyHandler), Moq.Times.Once);
}

programmatically change a dependency in Castle Windsor

I have a class that calls out to an internet service to get some data:
public class MarketingService
{
private IDataProvider _provider;
public MarketingService(IDataProvider provider)
{
_provider = provider;
}
public string GetData(int id)
{
return _provider.Get(id);
}
}
Currently I have two providers: HttpDataProvider and FileDataProvider. Normally I will wire up to the HttpDataProvider but if the external web service fails, I'd like to change the system to bind to the FileDataProvider . Something like:
public string GetData(int id)
{
string result = "";
try
{
result = GetData(id); // call to HttpDataProvider
}
catch (Exception)
{
// change the Windsor binding so that all future calls go automatically to the
// FileDataProvier
// And while I'm at it, retry against the FileDataProvider
}
return result;
}
So when this has been executed all future instances of MarketingService will automatically be wired up to the FileDataProvider. How to change a Windsor binding on the fly?
One solution would be using selector
public class ForcedImplementationSelector<TService> : IHandlerSelector
{
private static Dictionary<Type, Type> _forcedImplementation = new Dictionary<Type, Type>();
public static void ForceTo<T>() where T: TService
{
_forcedImplementation[typeof(TService)] = typeof(T);
}
public static void ClearForce()
{
_forcedImplementation[typeof(TService)] = null;
}
public bool HasOpinionAbout(string key, Type service)
{
return service == typeof (TService);
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
var tService = typeof(TService);
if (_forcedImplementation.ContainsKey(tService) && _forcedImplementation[tService] != null)
{
return handlers.FirstOrDefault(handler => handler.ComponentModel.Implementation == _forcedImplementation[tService]);
}
// return default
return handlers[0];
}
}
Test and usage
[TestFixture]
public class Test
{
[Test]
public void ForceImplementation()
{
var container = new WindsorContainer();
container.Register(Component.For<IFoo>().ImplementedBy<Foo>());
container.Register(Component.For<IFoo>().ImplementedBy<Bar>());
container.Kernel.AddHandlerSelector(new ForcedImplementationSelector<IFoo>());
var i = container.Resolve<IFoo>();
Assert.AreEqual(typeof(Foo), i.GetType());
ForcedImplementationSelector<IFoo>.ForceTo<Bar>();
i = container.Resolve<IFoo>();
Assert.AreEqual(typeof(Bar), i.GetType());
ForcedImplementationSelector<IFoo>.ClearForce();
i = container.Resolve<IFoo>();
Assert.AreEqual(typeof(Foo), i.GetType());
}
}
Alternatively you could create a proxy:
public class AutoSelectingDataProvider : IDataProvider
{
public AutoSelectingDataPovider(HttpDataProvider httpDataProvider, FallBackDataProvider fallBackProvider)
{
_httpDataProvider = httpDataProvider;
_fallBackDataProvider = fallBackDataProvider;
}
public string GetData(int id)
{
try
{
return _httpDataProvider.GetData(id);
}
catch (Exception)
{
return _fallBackDataProvider.GetData(id);
}
return result;
}
}
container.Register(
Component.For<HttpDataProvider>(),
Component.For<FallBackDataProvider>(),
Component.For<IDataProvider>().ImplementedBy<FallBackDataProvider>());
This will always first try to get data from the HttpDataProvider if not succesfull use the fallback. If you want you can introduce state and after a failure always use the fallback. This way you can keep using the IDataProvider in your application without needing to obtain a new one from the container.

Categories