如何运行 STA线程中的NUnit测试?
How to run NUnit test in STA thread?
我们正在将 WPF 应用程序移植到 .NET Core 3,预览版 5。
一些 NUnit 测试需要在 STA 线程中 运行。如何做到这一点?
None 的属性,如 [STAThread]、[RequiresSTA],... 有效。
这也不起作用:[assembly: RequiresThread(ApartmentState.STA)]
Apparent 命名空间似乎没有在 .NET Core 3 中公开。
有人做过吗?
ApartmentAttribute
首先在 NUnit 3.12 中为 .NET Standard 2.0 启用。
首先更新您的 NUnit 框架版本,然后使用 [Apartment(ApartmentState.STA)]
。
为了在 .Net Core 3 中的 WPF 单元测试中使用 STA,您需要添加扩展方法属性。
添加此 class
public class STATestMethodAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
return Invoke(testMethod);
TestResult[] result = null;
var thread = new Thread(() => result = Invoke(testMethod));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return result;
}
private TestResult[] Invoke(ITestMethod testMethod)
{
return new[] { testMethod.Invoke(null) };
}
}
然后用作
[STATestMethod]
public void TestA()
{
// Arrange
var userControlA = new UserControl();
//Act
// Assert
}
我最近将我的应用程序移植到 .Net 6,但无法正常工作。
但是 - 实施 IWrapTestMethod
似乎有效:
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
namespace NunitExtensions;
/// <summary>
/// This attribute forces the test to execute in an STA Thread.
/// Needed for UI testing.
/// The NUnit <see cref="NUnit.Framework.ApartmentAttribute"/> does not seem to work on .Net 6....
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class UITestAttribute : NUnitAttribute, IWrapTestMethod
{
public TestCommand Wrap(TestCommand command)
{
return Thread.CurrentThread.GetApartmentState() == ApartmentState.STA
? command
: new StaTestCommand(command);
}
private class StaTestCommand : TestCommand
{
private readonly TestCommand _command;
public StaTestCommand(TestCommand command) : base(command.Test)
{
_command = command;
}
public override TestResult Execute(TestExecutionContext context)
{
TestResult? result = null;
var thread = new Thread(() => result = _command.Execute(context));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return result ?? throw new Exception("Failed to run test in STA!");
}
}
}
我们正在将 WPF 应用程序移植到 .NET Core 3,预览版 5。 一些 NUnit 测试需要在 STA 线程中 运行。如何做到这一点?
None 的属性,如 [STAThread]、[RequiresSTA],... 有效。 这也不起作用:[assembly: RequiresThread(ApartmentState.STA)]
Apparent 命名空间似乎没有在 .NET Core 3 中公开。
有人做过吗?
ApartmentAttribute
首先在 NUnit 3.12 中为 .NET Standard 2.0 启用。
首先更新您的 NUnit 框架版本,然后使用 [Apartment(ApartmentState.STA)]
。
为了在 .Net Core 3 中的 WPF 单元测试中使用 STA,您需要添加扩展方法属性。 添加此 class
public class STATestMethodAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
return Invoke(testMethod);
TestResult[] result = null;
var thread = new Thread(() => result = Invoke(testMethod));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return result;
}
private TestResult[] Invoke(ITestMethod testMethod)
{
return new[] { testMethod.Invoke(null) };
}
}
然后用作
[STATestMethod]
public void TestA()
{
// Arrange
var userControlA = new UserControl();
//Act
// Assert
}
我最近将我的应用程序移植到 .Net 6,但无法正常工作。
但是 - 实施 IWrapTestMethod
似乎有效:
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
namespace NunitExtensions;
/// <summary>
/// This attribute forces the test to execute in an STA Thread.
/// Needed for UI testing.
/// The NUnit <see cref="NUnit.Framework.ApartmentAttribute"/> does not seem to work on .Net 6....
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class UITestAttribute : NUnitAttribute, IWrapTestMethod
{
public TestCommand Wrap(TestCommand command)
{
return Thread.CurrentThread.GetApartmentState() == ApartmentState.STA
? command
: new StaTestCommand(command);
}
private class StaTestCommand : TestCommand
{
private readonly TestCommand _command;
public StaTestCommand(TestCommand command) : base(command.Test)
{
_command = command;
}
public override TestResult Execute(TestExecutionContext context)
{
TestResult? result = null;
var thread = new Thread(() => result = _command.Execute(context));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return result ?? throw new Exception("Failed to run test in STA!");
}
}
}