Test project is double checking my controllers
I created a github repository for this specific post which can be found at https://github.com/CrazyInCode/WebApiNServiceBus
What I am trying to do is write tests for my WebApi application. In my spec tests, I ...
- Creating an HttpClient to use WebApi
- Calling my WebApi via HttpClient
- Serializing the result to a list
- Enforcing the NServiceBus Call
All of this can be found here .
I also use StructureMap, which I think is scanning my ApiControllers. It looks like NServiceBus is scanning my ApiControllers as well, because when I try to run my tests I get an error:
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
It is not easy to spot the error. I should...
- Place a breakpoint at lines 21 and 26 in the Global.cs project (Specs)
- Debug the test and make sure the test stops at the first breakpoint
- An overview
http://localhost:81/ValService/api/values/assets
that will just load ... - Continue testing and make sure the test stops at the last breakpoint.
- See results in a web browser
If I delete all lines containing IBus and follow the steps above, the test passes. Obviously NServiceBus has something to do with failing the test.
As I said, it looks like NServiceBus is scanning my assemblies for controllers. To prevent this, I tried adding this line to Global.cs to indicate that NServiceBus should scan, but with no success.
Configure.With(Enumerable.Empty<Assembly>());
The main components of the solution are WebApi, NServiceBus, StructureMap, FakeItEasy and SpecFlow.
I am stuck. How can I take the test?
Edit: Perhaps the solution is to force WebApi not to register controllers - just leave that up to NServiceBus? How can I try this?
source to share
Update: With FakeItEasy 1.19.0, this shouldn't happen. FakeItEasy will only check builds on disk if you explicitly request this behavior by implementing a custom Bootstrapper .
I don't know how StructureMap and NServiceBus work, but as luck would have it, just this morning I posted a blog post about how FakeItEasy scans assemblies , and I think it has some answers for you.
Highlights: the copies of the assemblies you see, and that @Aliostad listed with System.AppDomain.CurrentDomain.GetAssemblies()
, are shadow copies, almost certainly made by the test runner ReSharper. You can instruct the runner not to make these copies.
FakeItEasy before version 1.13 will check all assemblies in the application domain and all DLL files in the application directory - this will load duplicate assemblies when shadow copying is enabled.
Since 1.13, there are two optimizations. First, if the assembly is already loaded, it will not reload it from the filesystem if the locations are the same. Unfortunately, shadow copies override this check.
The second optimization might help you - FakeItEasy will load assemblies from disk for reflection only, and if the assembly does not reference FakeItEasy it will not be fully loaded and its types will not be checked. Since there are far fewer assemblies to be fully loaded, you can avoid the duplicate type problem.
I suggest building FakeItEasy 1.13. Try using shadow copies as well. Hell, even just disabling shadow copies with your current version might help.
source to share
This may not be the answer you can find, but these assemblies are loaded twice (just use 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}
And when you actually look at the location, this is what it shows:
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"
I suppose it has something to do with how the unit tests are executed.
source to share