2009-02-12 13 views
21

Piszę interfejs wiersza polecenia do mojego projektu. Użytkownik wprowadza "create project foo" i znajduje kontroler odpowiedzialny za "projekt", a następnie wywołuje metodę Create, przekazując "foo" jako pierwszy argument.Czy mogę uzyskać Moq, aby dodać atrybuty do klasy próbnej?

Opiera się w dużej mierze od cech i refleksji: kontroler wygląda mniej więcej tak:

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

chciałbym używać Moq w testach jednostkowych dla parsera, coś takiego:

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

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

controller.VerifyAll(); 

Dodanie atrybutów do interfejsu nie działa - nie są one dziedziczone przez klasy pochodne.

Czy mogę uzyskać Moq, aby dodać atrybuty do wyśmiewanej klasy?

Odpowiedz

31

Aktualizacja: Właśnie sobie sprawę, że rzeczywiście można dodać atrybutów do istniejącego typu za pomocą TypeDescriptor.AddAttributes, które mogą być wykonywane przed wystąpieniem lub aa typu:

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); 

Jeśli jest to potrzebne, AddAttribute zwraca TypeDescriptorProvider, który można przekazać do TypeDescriptor.RemoveProvider, aby później usunąć atrybuty.

Należy pamiętać, że Attribute.GetCustomAttributes nie znajdzie atrybutów dodanych w czasie wykonywania w ten sposób. Zamiast tego użyj TypeDescriptor.GetAttributes.

Original Odpowiedź

Nie wierzę Min (lub innego szyderczy ramy dla tej sprawy) obsługuje niestandardowych atrybutów. Wiem, że Castle Proxy (struktura powszechnie używana do tworzenia klasy) obsługuje, ale nie byłoby sposobu na dostęp do niego poprzez Moq.

Twoim najlepszym rozwiązaniem jest streszczenie metody ładowania atrybutów do interfejsu (który akceptuje typ i typ atrybutu), a następnie kpisz z tego.

Edycja: Na przykład

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); 
    } 
} 

Klasa musi atrybuty wykorzystuje wystąpienie IAttributeStrategy (za pomocą pojemnika IoC lub mają to ewentualnie przeszły do ​​konstruktora). Zwykle będzie to DefaultAttributeStrategy, ale możesz teraz sfałszować IAttributeStrategy, aby nadpisać dane wyjściowe.

Może wydawać się zawiłe, ale dodanie warstwy abstrakcji jest znacznie łatwiejsze niż próba sfałszowania atrybutów.

+0

Czy możesz rozwinąć podejście interfejsu? Nie sądzę, żeby to pasowało do tego, co robię, ale chciałbym to zobaczyć. –

+0

Zobacz moją zaktualizowaną odpowiedź na TypeDescriptor.AddAttributes –

+0

(daj mi znać, jeśli moja zaktualizowana odpowiedź rozwiąże problem i usuń stare części odpowiedzi) –