2009-02-12 4 views
21

Estoy escribiendo una interfaz de línea de comandos para mi proyecto. El usuario ingresa "crear proyecto foo", y encuentra el controlador responsable de "proyecto" y luego invoca el método Create, pasando "foo" como primer argumento.¿Puedo obtener Moq para agregar atributos a la clase simulada?

Se basa en gran medida de los atributos y la reflexión: el controlador se ve algo como esto:

[ControllerFor("project")] 
class ProjectController 
{ 
    [ControllerAction("create")] 
    public object Create(string projectName) { /* ... */ } 
} 

Me gustaría utilizar Moq en las pruebas unitarias para el analizador, algo como esto:

Mock<IProjectsController> controller = new Mock<IProjectsController>(); 
controller.Expect(f => f.Create("foo")); 

parser.Register(controller.Object); 
parser.Execute("create project foo"); 

controller.VerifyAll(); 

Agregar los atributos a la interfaz no parece funcionar; no son heredados por las clases derivadas.

¿Puedo obtener Moq para agregar atributos a la clase que se está burlando?

Respuesta

31

Actualización: Me acabo de dar cuenta de que en realidad se puede agregar atributos a un tipo existente mediante el uso de TypeDescriptor.AddAttributes, que puede ser ejecutado en una instancia o AA Tipo:

Mock<IRepository> repositoryMock = new Mock<IRepository>(); 

CustomAttribute attribute = new CustomAttribute(); 

// option #1: to the instance 
TypeDescriptor.AddAttributes(repositoryMock.Object, attribute); 

// option #2: to the generated type 
TypeDescriptor.AddAttributes(repositoryMock.Object.GetType(), attributes); 

Si lo necesita, AddAttribute devuelve un TypeDescriptorProvider que se puede pasar al TypeDescriptor.RemoveProvider para eliminar los atributos posteriormente.

Tenga en cuenta que Attribute.GetCustomAttributes no encontrará los atributos agregados en el tiempo de ejecución de esta manera. En su lugar, use TypeDescriptor.GetAttributes.

respuesta original

No belive Moq (o cualquier otro marco de burla para el caso) es compatible con los atributos personalizados. Sé que Castle Proxy (el marco comúnmente utilizado para crear la clase) lo hace compatible con, pero no habría forma de acceder a él a través de Moq.

Su mejor opción es abstraer su método de cargar atributos en una interfaz (que acepta el tipo y el tipo de atributo) y luego simular eso.

Editar: Por ejemplo:

public interface IAttributeStrategy 
{ 
    Attribute[] GetAttributes(Type owner, Type attributeType, bool inherit); 
    Attribute[] GetAttributes(Type owner, bool inherit); 
} 

public class DefaultAttributeStrategy : IAttributeStrategy 
{ 
    public Attribute[] GetAttributes(Type owner, Type attributeType, bool inherit) 
    { 
     return owner.GetCustomAttributes(attributeType, inherit); 
    } 

    public Attribute[] GetAttributes(Type owner, bool inherit) 
    { 
     return owner.GetCustomAttributes(inherit); 
    } 
} 

La clase que las necesidades de los atributos utiliza una instancia de IAttributeStrategy (ya sea a través de un contenedor IoC, o tener que pasar opcionalmente en el constructor). Por lo general, será una DefaultAttributeStrategy, pero ahora puede simular IAttributeStrategy para anular la salida.

Puede sonar intrincado, pero agregar una capa de abstracción es mucho más fácil que tratar de simular en realidad los Atributos.

+0

¿Podría ampliar el enfoque de la interfaz? No creo que encaje con lo que estoy haciendo, pero me gustaría verlo para estar seguro. –

+0

Ver mi respuesta actualizada en TypeDescriptor.AddAttributes –

+0

(avíseme si mi respuesta actualizada resuelve su problema y eliminaré las partes anteriores de la respuesta) –

Cuestiones relacionadas