Код модульного тестирования, который использует autofac в качестве IoC-контейнера - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть простая структура, которая позволяет «всему» подписываться на события, учитывая, что «Страж» пройден.Синтаксис объявления выглядит следующим образом:

public class MyObject : ICanHandle<MySuperAwesomeEvent, GivenYouAreLeetGuard> { .... }

Защиту можно создать двумя различными способами.Либо путем регистрации в контейнере с использованием этого метода расширений

public static void RegisterCommandGuard<TCommandGuard>(this ContainerBuilder builder)
  where TCommandGuard : IExecuteGuard
 {
     var type = typeof(TCommandGuard);
     var typeName = type.FullName;
     builder.RegisterType<TCommandGuard>().Named(typeName, type);
 }

, либо он будет создан с использованием отражения во время разрешения этого компонента в моей структуре.

public bool CanExecute(object message)
{
    object resolvedType = null;
    var name = CanExecuteGuard.FullName;
    if(!_componentContext.TryResolveNamed(name, typeof(IExecuteGuard), out resolvedType))
    {
        try
        {
            resolvedType = (IExecuteGuard)Activator.CreateInstance(CanExecuteGuard);
        }
        catch (Exception e)
        {
            throw new Exception($"Cannot locate {name} in container nor create an instance of it. See inner exception:", e);
        }
    }

    return ((IExecuteGuard)resolvedType).CanExecute(message);
}

Запуск этого в моем приложении работает, как я ожидаю, но в моих тестах я не могу разрешить ни одного из «Стражей».

[Fact]
public void EventAggregator_GivenGuardWithDependencies_ShouldFireEventToAllSubscribers()
{
    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterType<UserRepository>().As<IUserRepository>();
    containerBuilder.RegisterCommandGuard<MustBeAdminGuard>();
    var container = containerBuilder.Build();

    using (var lifeTimeScope = container.BeginLifetimeScope())
    {
        var eventAggregator = new ExtendedEventAggregator(lifeTimeScope);
        var @object = new ObjectWhichHandlesUsers();
        eventAggregator.Subscribe(@object);
        eventAggregator.PublishOnUIThread(new FireEmployeeCommand(userId: 1, userToFireId: 5));
        @object.UserIds.Should().HaveCount(6);
    }
}

TryResolveNamedМетод в IComponentContext никогда не найдет мою зарегистрированную охрану.Глядя на отладчик, я ясно вижу, что «что-то» как-то зарегистрировано

enter image description here

Что я здесь не так делаю?Другие предложения о том, как улучшить код, также сопровождаются комментариями.Спасибо!

РЕДАКТИРОВАТЬ:

Во время отладки моего модульного теста я пытался проверить, был ли зарегистрирован гвардеец, введя следующее в окне Immidiate вVisual Studio:

lifeTimeScope.IsRegisteredWithName("Caliburn.Micro.Demo.Tests.MustBeAdminGuard",typeof(MustBeAdminGuard))

И этот запрос возвращает true.В чем реальная разница, передавая IComponentContext вместо ILifeTimeScope?Я думал, что этот интерфейс только выставил подмножество методов, выставленных ILifeTimeScope ..

1 Ответ

0 голосов
/ 01 января 2019

У меня есть что-то похожее на тест, и оно работает, но я знаю, где ваша проблема, вы зарегистрировали тип MustBeAdminGuard и хотите разрешить другой тип IExecuteGuard, поэтому не ожидайте, что он будет работать так:)

Таким образом, чтобы решить эту проблему, нужно изменить регистрирующую часть в классе RegisterCommandGuard.У вас есть две возможности выбрать то, что вы хотите

//1. looks better
builder.RegisterType<TCommandGuard>().Named<IExecuteGuard>(typeName);

//2.
builder.RegisterType<TCommandGuard>().Named(typeName, typeof(IExecuteGuard));

Дайте мне знать, если это решило вашу проблему, нужно ^^, так как я проверил это на общем примере.

...