Lo scenario che attualmente dispongo è che sto scrivendo un test unitario per un codice che utilizza un'altra libreria di codice che utilizza l'iniezione di dipendenza e fornisce un UnitContainerExtension per l'avvio di tutte le classi concrete richiesto dalla biblioteca. Tuttavia nel mio test unitario voglio essere in grado di prendere in giro uno o due tipi registrati. Ora, in teoria, in base a tutto il post che ho visto, non ci dovrebbero essere problemi con la registrazione e quindi la registrazione di un nuovo tipo. Quest'ultima definizione/mappatura sostituisce la prima.Sostituzione del tipo registrato in Unity RegisterType <TFrom, TTo> vs ReigsterType <T>
Tuttavia questo non sembra funzionare nella pratica. Ora potrei semplicemente copiare l'elenco di tipo di registrazione dall'estensione delle librerie e ommit/modificare quelli che ho bisogno di prendere in giro. Tuttavia ho pensato che questo non mi sembra giusto e forse mi manca qualcosa.
Il seguente è un esempio del codice (che è stato semplificato e aveva l'UnitContainerExtension inline):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Moq;
namespace UnityTest
{
class Program
{
private static IFooBar _mockFooBar;
public static IFooBar MockFooBar
{
get
{
return _mockFooBar ?? (_mockFooBar = Mock.Of<IFooBar>(fb => fb.Test(It.IsAny<string>()) == "I am mockery of FooBar!"));
}
}
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
//Registration of concrete class done inside extension
container.RegisterType<IFooBar, FooBar>();
//Re-registering
container.RegisterType<IFooBar>(new InjectionFactory(uc => MockFooBar));
//This should resolve to the mocked foobar but doesn't
Console.WriteLine(container.Resolve<IFooBar>().Test("I am the concrete FooBar!"));
Console.ReadLine();
}
public interface IFooBar
{
string Test(string text);
}
public class FooBar : IFooBar
{
public string Test(string text)
{
// Some concrete code
return text;
}
}
}
}
Tuttavia il tipo IFooBar risolve alla classe FooBar concreta anziché la versione deriso.
ho il sospetto che chiamare RegesterType <T> invece di RegisterType < TFrom, TTO > quando ri-registrazione potrebbe essere il problema.
La seguente è una schermata del contenitore in fase di esecuzione dopo la seconda chiamata a RegisterType:
anche lo stesso sembra accadere con un'altra classe 'non deriso', che non è così sorprendente come si spera Unità non sta guardando il tipo di mappato all'oggetto.
Utilizzando il seguente fonte esempio modificato:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Moq;
namespace UnityTest
{
class Program
{
private static IFooBar _mockFooBar;
public static IFooBar MockFooBar
{
get
{
return _mockFooBar ?? (_mockFooBar = Mock.Of<IFooBar>(fb => fb.Test(It.IsAny<string>()) == "I am mockery of FooBar!"));
}
}
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
//Registration of concrete class done inside extension
container.RegisterType<IFooBar, FooBar>();
//Re-registering
container.RegisterType<IFooBar>(new InjectionFactory(uc => MockFooBar));
//Re-registering
container.RegisterType<IFooBar>(new InjectionFactory(uc => new FooBar2()));
//This should resolve to the mocked foobar but doesn't
Console.WriteLine(container.Resolve<IFooBar>().Test("I am the original FooBar!"));
Console.ReadLine();
}
public interface IFooBar
{
string Test(string text);
}
public class FooBar : IFooBar
{
public string Test(string text)
{
// Some concrete code
return text;
}
}
public class FooBar2 : IFooBar
{
public string Test(string text)
{
// Some concrete code
return "FooBar 2.0";
}
}
}
}
dà gli stessi risultati - questa è la prima registrazione viene utilizzato su qualsiasi di quelli successivi:
hai usato un debugger per vedere se il metodo factory viene richiamato? – mmilleruva
Sì, un punto di interruzione sulla proprietà MockFooBar non viene toccato. Inoltre, se ispezionate il container in fase di esecuzione e date un'occhiata alla proprietà Registrations, potete vedere che la registrazione sta ancora puntando alla classe concreta. –