当 运行 XUnit 测试在 vs 测试资源管理器中导致模拟异常时,CSLAs WCF 的使用

CSLAs WCF usage when running XUnit tests in vs test explorer causes an Impersonation Exception

我们将 NuGet 的 XUnit 2.1.0 与相关 运行 人员、控制台和视觉工作室一起使用,如 "running tests with visual studio" 标题和相关内容下记录的 here

我也在使用 Visual Studio 2015 Enterprise Update 2。 唯一合理过时的是 CSLA,我们使用的是 4.0.1(我想 5 岁了?)

当我们 运行 任何需要 DataPortal 提取的测试时,只要 DataPortal 提取尝试发送到服务器,测试就会失败。 WCF 抛出一个 "System.ServiceModel.FaultException" 说明 "Invalid token for impersonation - it cannot be duplicated." 重要的是要注意 none 的测试试图模拟另一个用户。跌倒发生在任何试图使用 CSLA 进行 DataPortal 调用的测试中。 我们最近通过 nuget 从 xunit 1.x 转移到 2.x,在本地测试我们的测试时,我们曾经从 xunit 运行ner 运行 xunit,但现在已弃用.通过 Gui 和控制台 运行ner for xunit 1.x 的所有测试都 运行 绝对没问题。现在我们必须将 visual studio 运行ner 与 xunit 2.x 一起使用,我们得到了这个疯狂的异常。

编辑:如果你 运行 xunit 2.x console 运行ner 来自 visual studio 之外,测试在 2.x 上也很好,它是 visual studio 无法正常工作的方面。

下面的堆栈跟踪:

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Csla.Server.Hosts.IWcfPortal.Fetch(FetchRequest request)
   at Csla.DataPortalClient.WcfProxy.Fetch(Type objectType, Object criteria, DataPortalContext context) in D:\Dev\Insight\Trunk\Source\Lib\CSLA .NET.0\Source\Csla\DataPortalClient\WcfProxy.cs:line 162
   at Csla.DataPortal.Fetch(Type objectType, Object criteria) in D:\Dev\Insight\Trunk\Source\Lib\CSLA .NET.0\Source\Csla\DataPortal.cs:line 245
   at Csla.DataPortal.Fetch[T](Object criteria) in D:\Dev\Insight\Trunk\Source\Lib\CSLA .NET.0\Source\Csla\DataPortal.cs:line 170

同样,如果我们 运行 来自另一个测试 运行ner 的测试,旧的 xunit 测试 运行ner 或 CruiseControl.Net 例如(我们使用CC.Net 用于持续集成,这 运行 测试很好)

我认为这更多的是 Visual Studio 测试 运行ner 设置当前用户主体的方式的问题。大多数其他测试 运行ners 似乎使用空的 GenericPrincipal,而 VS 似乎将当前主体设置为当前 windows 身份的模拟版本。这意味着当 CSLA.NET 再次尝试模拟它时,您会看到您看到的错误。

此问题在与 NUnit 相关的博客 post 中进行了详细讨论:http://www.ienumerable.it/2015/03/21/Setting-up-good-fixture.html

用 xUnit 解决这个问题的一个相对简单的方法(改编自上面的博客)是设置一个 BeforeAfterTestAttribute 以在测试 运行s 之前将其设置为 GenericPrincipal,然后在之后恢复原始主体。这保证它将 运行 使用相同的主体,而不管使用的测试 运行ner。

public class RequiresGenericPrincipalAttribute : BeforeAfterTestAttribute
{
    private IPrincipal _originalPrincipal;
    public override void Before(MethodInfo methodUnderTest)
    {
        _originalPrincipal = System.Threading.Thread.CurrentPrincipal;
        System.Threading.Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(""), new String[] { });
        base.Before(methodUnderTest);                        
    }

    public override void After(MethodInfo methodUnderTest)
    {
        base.After(methodUnderTest);
        System.Threading.Thread.CurrentPrincipal = _originalPrincipal;
    }

}