首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用autofac作为IoC容器的单元测试代码

使用autofac作为IoC容器的单元测试代码
EN

Stack Overflow用户
提问于 2018-12-19 07:28:27
回答 1查看 137关注 0票数 0

我有一个简单的框架,它将允许“一切”订阅事件,因为“警卫”已经通过。声明它的语法如下所示:

代码语言:javascript
复制
public class MyObject : ICanHandle<MySuperAwesomeEvent, GivenYouAreLeetGuard> { .... }

守卫可以通过两种不同的方式创建。通过使用此扩展方法在容器中注册

代码语言:javascript
复制
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);
 }

或者,它将通过在我的框架中解决这个组件时使用反射来创建。

代码语言:javascript
复制
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);
}

在我的应用程序中运行这一点正如我所期望的那样,但是在我的测试中,我无法解决任何“警卫”问题。

代码语言:javascript
复制
[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中永远找不到我的注册守卫。查看调试器,我可以清楚地看到“某事”是以某种方式注册的。

我在这里做错什么了?关于如何改进代码的其他建议也提供了评论。谢谢!

编辑:

在调试单元测试期间,我试图通过在Visual的Immidiate窗口中键入以下内容来检查是否注册了卫队:

代码语言:javascript
复制
lifeTimeScope.IsRegisteredWithName("Caliburn.Micro.Demo.Tests.MustBeAdminGuard",typeof(MustBeAdminGuard))

这个查询返回true。传递IComponentContext而不是ILifeTimeScope的真正区别是什么?我认为这个接口只公开了ILifeTimeScope公开的方法的一个子集。

EN

回答 1

Stack Overflow用户

发布于 2019-01-01 14:15:21

我有类似于我自己的测试smth,它正在工作,但我知道您的问题在哪里,您已经注册了MustBeAdminGuard类型,并且您希望解决不同类型的IExecuteGuard,所以不要期望它会像这样工作:)

因此,要解决这个问题,您必须更改类RegisterCommandGuard中的注册部分。你有两种选择你想要的

代码语言:javascript
复制
//1. looks better
builder.RegisterType<TCommandGuard>().Named<IExecuteGuard>(typeName);

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

让我知道,如果它解决了你的问题,它必须^^,因为我已经在普通的例子中测试过它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53846452

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档