Подтвердить что ты не робот

Могу ли я получить Moq для добавления атрибутов в класс mock?

Я пишу интерфейс командной строки для своего проекта. Пользователь вводит "создать проект foo", и он обнаруживает контроллер, ответственный за "проект", а затем вызывает метод Create, передавая "foo" в качестве первого аргумента.

Он в значительной степени опирается на атрибуты и отражение: контроллер выглядит примерно так:

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

Я хотел бы использовать Moq в модульных тестах для синтаксического анализатора, примерно так:

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

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

controller.VerifyAll();

Добавление атрибутов в интерфейс не работает - они не наследуются производными классами.

Могу ли я получить Moq для добавления атрибутов в класс, который насмехается?

4b9b3361

Ответ 1

Обновление: Я только что понял, что вы действительно можете добавлять атрибуты к существующему типу, используя TypeDescriptor.AddAttributes, который может быть выполнен против экземпляра или типа aa:

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

Если вам это нужно, AddAttribute возвращает TypeDescriptorProvider, который может быть передан TypeDescriptor.RemoveProvider, чтобы впоследствии удалить атрибуты.

Помните, что Attribute.GetCustomAttributes не найдет атрибуты, добавленные во время выполнения таким образом. Вместо этого используйте TypeDescriptor.GetAttributes.

Оригинальный ответ

Я не верю, что Moq (или любая другая насмешличная структура) поддерживает пользовательские атрибуты. Я знаю, что Castle Proxy (структура, обычно используемая для создания класса) поддерживает, но доступ к ней через Moq не будет.

Лучше всего отвлечь свой метод загрузки атрибутов в интерфейс (который принимает тип и тип атрибута), а затем издеваться над этим.

Изменить: Например:

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

Класс, который нуждается в атрибутах, использует экземпляр IAttributeStrategy (либо через контейнер IoC, либо необязательно переданный в конструктор). Обычно это будет DefaultAttributeStrategy, но теперь вы можете высмеять IAttributeStrategy, чтобы переопределить вывод.

Это может показаться запутанным, но добавление слоя абстракции намного проще, чем попытка на самом деле издеваться над атрибутами.