测试项目扫描我的控制器两次

时间:2013-01-21 11:44:30

标签: asp.net-web-api structuremap nservicebus specflow fakeiteasy

我为这个特定的帖子创建了一个github repo,可以在https://github.com/CrazyInCode/WebApiNServiceBus找到

我要做的是为我的WebApi应用程序编写测试。在我的规格测试中,我...

  1. 创建HttpClient以使用WebApi
  2. 通过HttpClient调用我的WebApi
  3. 将结果序列化为列表
  4. 确保已调用NServiceBus
  5. 所有这一切都可以找到here

    我也在使用StructureMap,我想我会扫描我的ApiControllers。似乎NServiceBus也扫描我的ApiControllers,因为当我尝试运行我的测试时,我得到错误:

    Multiple types were found that match the controller named 'values'. This can happen if the route that services this request ('api/{controller}/{id}') found multiple controllers defined with the same name but differing namespaces, which is not supported. The request for 'values' has found the following matching controllers: WebApiNServiceBus.Proj.Controllers.ValuesController WebApiNServiceBus.Proj.Controllers.ValuesController
    

    实际发现错误并不简单。我必须......

    1. 在Global.cs(规范项目)
    2. 的第21和26行放置一个断点
    3. 调试测试并确保测试在第一个断点处停止
    4. 浏览只会加载的http://localhost:81/ValService/api/values/assets ...
    5. 继续测试并确保测试在最后一个断点处停止
    6. 在网络浏览器中查看结果
    7. 如果我删除所有包含IBus的行,并执行上述步骤 - 测试通过。显然,NServiceBus与测试失败有关。

      正如我之前所说,似乎NServiceBus扫描我的程序集中的控制器。为了防止这种情况,我尝试在Global.cs中添加此行以指定NServiceBus应扫描的内容 - 但没有成功。

      Configure.With(Enumerable.Empty<Assembly>());
      

      解决方案的主要组件是WebApi,NServiceBus,StructureMap,FakeItEasy和SpecFlow。

      我被困住了。我怎样才能通过考试?

      编辑:也许解决方案是让WebApi不注册控制器 - 只需将它留给NServiceBus?我怎么试试呢?

2 个答案:

答案 0 :(得分:1)

这可能不是您可能正在寻找的答案,但这些程序集已加载两次(只需使用System.AppDomain.CurrentDomain.GetAssemblies()):

System.AppDomain.CurrentDomain.GetAssemblies()
{System.Reflection.RuntimeAssembly[70]}
    [0]: {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [1]: {JetBrains.ReSharper.TaskRunnerFramework, Version=6.1.1000.82, Culture=neutral, PublicKeyToken=1010a0d8d6380325}
    [2]: {System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [3]: {System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [4]: {JetBrains.ReSharper.UnitTestRunner.nUnit, Version=6.1.1000.82, Culture=neutral, PublicKeyToken=1010a0d8d6380325}
    [5]: {System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [6]: {nunit.core.interfaces, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77}
    [7]: {nunit.core, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77}
    [8]: {nunit.util, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77}
    [9]: {WebApiNServiceBus.Proj.Specs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
    [10]: {System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [11]: {StructureMap, Version=2.6.4.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223}
    [12]: {System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [13]: {TechTalk.SpecFlow, Version=1.9.0.77, Culture=neutral, PublicKeyToken=0778194805d6db41}
    [14]: {nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77}
    [15]: {Anonymously Hosted DynamicMethods Assembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null}
    [16]: {System.Web.Http.SelfHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [17]: {System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [18]: {WebApiNServiceBus.Proj, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
    [19]: {System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [20]: {System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [21]: {SMDiagnostics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [22]: {System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [23]: {System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [24]: {Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed}
    [25]: {System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [26]: {Microsoft.VisualStudio.Debugger.Runtime, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [27]: {NServiceBus, Version=3.3.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c}
    [28]: {FakeItEasy, Version=1.7.4626.65, Culture=neutral, PublicKeyToken=eff28e2146d5fd2c}
    [29]: {Castle.Core, Version=3.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc}
    [30]: {FakeItEasy, Version=1.7.4626.65, Culture=neutral, PublicKeyToken=eff28e2146d5fd2c}
    [31]: {log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821}
    [32]: {Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed}
    [33]: {NServiceBus.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c}
    [34]: {NServiceBus, Version=3.3.0.0, Culture=neutral, PublicKeyToken=9fc386479f8a226c}
    [35]: {nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77}
    [36]: {StructureMap, Version=2.6.4.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223}
    [37]: {System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [38]: {System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [39]: {System.Web.Http.SelfHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [40]: {System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [41]: {TechTalk.SpecFlow, Version=1.9.0.77, Culture=neutral, PublicKeyToken=0778194805d6db41}
    [42]: {WebApiContrib.IoC.StructureMap, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
    [43]: {WebApiNServiceBus.Proj, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
    [44]: {WebApiNServiceBus.Proj.Specs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
    [45]: {Castle.Core, Version=3.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc}
    [46]: {System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [47]: {System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [48]: {System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [49]: {System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [50]: {System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [51]: {log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821}
    [52]: {System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [53]: {System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [54]: {System.Data.SqlXml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [55]: {System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [56]: {System.ServiceModel.Internals, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [57]: {System.Runtime.DurableInstancing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [58]: {System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
    [59]: {System.Messaging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [60]: {System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [61]: {Microsoft.Transactions.Bridge, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [62]: {System.Web.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [63]: {DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69}
    [64]: {WebApiContrib.IoC.StructureMap, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
    [65]: {Accessibility, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [66]: {System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [67]: {System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    [68]: {System.DirectoryServices.Protocols, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
    [69]: {System.Xml.Linq, Version=4.0.0.0, Culture=neutral, 
PublicKeyToken=b77a5c561934e089}

当你真正看到这个位置时,这就是它所显示的内容:

System.AppDomain.CurrentDomain.GetAssemblies()[43].Location
"C:\\Users\\alik\\GitHub\\WebApiNServiceBus\\WebApiNServiceBus.Proj.Specs\\bin\\Debug\\WebApiNServiceBus.Proj.dll"
System.AppDomain.CurrentDomain.GetAssemblies()[44].Location
"C:\\Users\\alik\\GitHub\\WebApiNServiceBus\\WebApiNServiceBus.Proj.Specs\\bin\\Debug\\WebApiNServiceBus.Proj.Specs.dll"
System.AppDomain.CurrentDomain.GetAssemblies()[9].Location
"C:\\Users\\alik\\AppData\\Local\\Temp\\nfx3urho.nhb\\WebApiNServiceBus.Proj.Specs\\assembly\\dl3\\6d69b640\\baacb725_f5f7cd01\\WebApiNServiceBus.Proj.Specs.dll"
System.AppDomain.CurrentDomain.GetAssemblies()[18].Location
"C:\\Users\\alik\\AppData\\Local\\Temp\\nfx3urho.nhb\\WebApiNServiceBus.Proj.Specs\\assembly\\dl3\\180be185\\4a3f842e_f3f7cd01\\WebApiNServiceBus.Proj.dll"

我相信这与单位测试的运行方式有关。

答案 1 :(得分:1)

更新:从FakeItEasy 1.19.0开始,这不应该发生。如果您explicitly ask for this behaviour by implementing a custom Bootstrapper,FakeItEasy将仅扫描磁盘上的程序集。

我不知道StructureMap和NServiceBus是如何工作的,但幸运的是,就在今天早上我发布了一篇关于how FakeItEasy scans assemblies的博客文章,我认为它有一些答案。

亮点:您看到的程序集副本以及使用System.AppDomain.CurrentDomain.GetAssemblies()列出的@Aliostad都是卷影副本,几乎可以肯定是由ReSharper测试运行程序制作的。您可以指示跑步者不要制作这些副本。

版本1.13之前的FakeItEasy会扫描应用程序域中的所有程序集以及应用程序目录中的所有DLL - 这会导致在启用卷影复制时加载重复的程序集。

1.13,有两个优化。第一个是如果程序集已经加载,如果位置匹配,它将不会从文件系统重新加载它。不幸的是,影子副本击败了这张支票。

第二个优化可以帮助你--FakeItEasy将从磁盘加载程序集仅用于反射,如果程序集不引用FakeItEasy,它将不会被完全加载,并且它的类型赢了“扫描。由于应该完全加载更少的程序集,因此可以避免重复类型问题。

我建议选择FakeItEasy 1.13。尝试使用阴影副本打开和关闭。哎呀,即使只是用当前版本关闭卷影副本也可能有所帮助。