3

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

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

  1. 创建一个 HttpClient 来使用 WebApi
  2. 通过 HttpClient 调用我的 WebApi
  3. 将结果序列化为列表
  4. 确保已调用 NServiceBus

所有这些都可以在这里找到。

我也在使用 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(Specs 项目)的第 21 和 26 行放置一个断点
  2. 调试测试并确保测试在第一个断点处停止
  3. 浏览http://localhost:81/ValService/api/values/assets将加载的...
  4. 继续测试并确保测试在最后一个断点处停止
  5. 在网络浏览器中查看结果

如果我删除所有包含 IBus 的行,并执行上述步骤 - 测试通过。显然 NServiceBus 与测试失败有关。

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

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

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

我被困住了。我怎样才能使我的测试通过?

编辑:也许解决方案是让 WebApi 不注册控制器 - 把它留给 NServiceBus?我怎么能试试这个?

4

2 回答 2

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"

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

于 2013-01-21T16:41:31.620 回答
1

更新:从FakeItEasy 1.19.0 开始,这不应该发生。如果您通过实现自定义 Bootstrapper 明确要求此行为, FakeItEasy 只会扫描磁盘上的程序集。

我不知道 StructureMap 和 NServiceBus 是如何工作的,但幸运的是,就在今天早上,我发表了一篇关于FakeItEasy 如何扫描程序集的博客文章,我认为它可以为您提供一些答案。

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

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

对于 1.13,有两个优化。第一个是如果一个程序集已经加载,如果位置匹配,它将不会从文件系统重新加载它。不幸的是,卷影副本无法通过此检查。

第二个优化可能对您有所帮助 - FakeItEasy 将从磁盘加载程序集仅用于反射,如果程序集不引用 FakeItEasy,则不会完全加载,也不会扫描其类型。由于应完全加载更少的程序集,因此您可以避免重复类型问题。

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

于 2013-07-08T14:25:48.403 回答