2014-10-27 28 views
1

我有一套由MsTest围绕OWIN执行的集成测试,使用OWIN启动方法作为自己的主机。 测试是很简单,请使用以下模式:当我运行在本地机器DEV测试MsTest和OWIN,重复控制器

WebApp.Start<Startup>(url: appAddress); 
HttpClient client = new HttpClient(); 
client.DefaultRequestHeaders 
    .Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
var response = client.GetAsync(uri).Result; 

,他们是绿色的。 当我们在Build Machine中运行来自Visual Studio的测试时,它们是绿色的。 如果他们从队列中运行,前几天,我们开始摆脱OWIN这个恼人的错误:

*** OWIN STARTED *** 
    {"Message":"An error has occurred.", 
"ExceptionMessage":"Multiple types were found that match the controller named 'xxx'. 
This can happen if the route that services this request ('odata/v1/{*odataPath}') found multiple controllers defined with the same name but differing namespaces, which is not supported. 
The request for 'xxx' has found the following matching controllers: 
namespace.V1.Controllers.xxxController 
namespace.V1.Controllers.xxxController", 
"ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.SelectController(HttpRequestMessage request) 
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"} 

而且因为我们使用温莎解决控制器和我们还打印出在温莎的注册,这是奇怪的当然,只有一个控制器具有该名称。只有在代码在MsBuild内执行时,我们才会在所有控制器上出现此问题......在Build Machine的Visual Studio或生产环境中,它可以工作。 可能是错误是别的东西,但被OWIN吞噬?

我:

+0

您使用的是哪个版本的owin? – 2015-01-23 01:38:36

+0

最新的应该是2.2 这是一个奇怪的问题,由于配置已重新编译后自动排除 – Raffaeu 2015-01-23 07:50:16

+0

我有与owin 3和nunit相同的问题,但它只发生在其中一个测试项目。 – 2015-01-23 10:55:13

回答

0

我们通过举办OWIN项目中的IIS表达

public class IisExpressRunner : IDisposable 
{ 
    /// <summary> 
    /// Stores whether this instance has been disposed. 
    /// </summary> 
    private Boolean _isDisposed; 

    /// <summary> 
    /// Stores the IIS Express process. 
    /// </summary> 
    private Process _process; 

    /// <summary> 
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 
    /// </summary> 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    /// <summary> 
    /// Starts IIS Express using the specified directory path and port. 
    /// </summary> 
    /// <param name="configPath"> 
    /// The directory path. 
    /// </param> 
    /// <param name="siteName"> 
    /// The port. 
    /// </param> 
    public void Start(String configPath, string siteName) 
    { 
     String iisExpressPath = DetermineIisExpressPath(); 
     String arguments = String.Format(
     CultureInfo.InvariantCulture, "/config:\"{0}\" /site:{1}", configPath, siteName); 

     ProcessStartInfo info = new ProcessStartInfo(iisExpressPath) 
     { 
      WindowStyle = ProcessWindowStyle.Hidden, 
      ErrorDialog = true, 
      LoadUserProfile = true, 
      CreateNoWindow = false, 
      UseShellExecute = false, 
      Arguments = arguments 
     }; 

     Thread startThread = new Thread(() => StartIisExpress(info)) 
     { 
      IsBackground = true 
     }; 

     startThread.Start(); 
    } 

    /// <summary> 
    /// Releases unmanaged and - optionally - managed resources. 
    /// </summary> 
    /// <param name="disposing"> 
    /// <c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources. 
    /// </param> 
    protected virtual void Dispose(Boolean disposing) 
    { 
     if (_isDisposed) 
     { 
      return; 
     } 

     if (disposing) 
     { 
      // Free managed resources 
      if (_process.HasExited == false) 
      { 
       _process.CloseMainWindow(); 
      } 

      _process.Kill(); 
      _process = null; 
     } 

     // Free native resources if there are any 
     _isDisposed = true; 
    } 

    /// <summary> 
    /// Determines the IIS express path. 
    /// </summary> 
    /// <returns> 
    /// A <see cref="String"/> instance. 
    /// </returns> 
    private static String DetermineIisExpressPath() 
    { 
     String iisExpressPath; 

     if (Environment.Is64BitOperatingSystem) 
     { 
      iisExpressPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); 
     } 
     else 
     { 
      iisExpressPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); 
     } 

     iisExpressPath = Path.Combine(iisExpressPath, @"IIS Express\iisexpress.exe"); 

     return iisExpressPath; 
    } 

    /// <summary> 
    /// Starts the IIS express. 
    /// </summary> 
    /// <param name="info"> 
    /// The info. 
    /// </param> 
    [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", 
    Justification = "Required here to ensure that the instance is disposed.")] 
    private void StartIisExpress(ProcessStartInfo info) 
    { 
     try 
     { 
      _process = Process.Start(info); 
      _process.WaitForExit(); 
     } 
     catch (Exception) 
     { 
      Dispose(); 
     } 
    } 
} 
0

我得到了同样的错误,在我的情况下,它是多种因素的组合解决了这个问题在我们的测试使用Nunit和Owin进行自我管理。 在测试中的设置,我开始的Web服务器:

_server = WebApp.Start<Startup>(new StartOptions(baseAddress)); 

在测试中的拆卸我杀了它:

_server.Dispose(); 

我的一个测试用TestCaseSource这是之前执行设置:

[TestCaseSource(typeof(TestData), "TestDataSource")] 
public void Test_With_Source(TestData testcase) 

下了线,内TestData.TestDataSource我加载包含控制器得到一些路由信息的组件:

loadedAssembly = Assembly.LoadFile(dll); //First load of the assembly 

在其中,web服务器启动(在设置)的集被加载过一次了(由TestCaseSource)的点,这样我最终得到了两次相同的程序集,并且web api抱怨同一个控制器的重复。

我修复是通过除去Assembly.LoadFile(DLL):

typeof(BaseController).Assembly 

即由含有BaseController未被加载两次组装。