Rya*_*yan 96 c# reflection nunit
我有一个单元测试(nUnit).调用堆栈中的许多层如果通过单元测试运行,则方法将失败.
理想情况下,你会使用像mocking这样的东西来设置这个方法所依赖的对象,但这是第三方代码,如果没有大量工作我就不能这样做.
我不想设置nUnit特定的方法 - 这里有太多的级别,并且它是一个很差的单元测试方法.
相反,我想要做的是在调用堆栈中添加类似这样的东西
#IF DEBUG // Unit tests only included in debug build
if (IsRunningInUnitTest)
{
// Do some setup to avoid error
}
#endif
Run Code Online (Sandbox Code Playgroud)
那么关于如何编写IsRunningInUnitTest的任何想法?
PS我完全清楚这不是很好的设计,但我认为它比替代品更好.
Jon*_*eet 73
我以前做过这个 - 我做的时候不得不捏住鼻子,但是我做到了.实用主义每次都击败教条主义.当然,如果是你可以重构,以避免它的好办法,那将是巨大的.
基本上我有一个"UnitTestDetector"类,它检查NUnit框架程序集是否已加载到当前的AppDomain中.它只需要执行一次,然后缓存结果.丑陋,但简单而有效.
Rya*_*yan 72
采取乔恩的想法这就是我想出的 -
using System;
using System.Reflection;
/// <summary>
/// Detect if we are running as part of a nUnit unit test.
/// This is DIRTY and should only be used if absolutely necessary
/// as its usually a sign of bad design.
/// </summary>
static class UnitTestDetector
{
private static bool _runningFromNUnit = false;
static UnitTestDetector()
{
foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
{
// Can't do something like this as it will load the nUnit assembly
// if (assem == typeof(NUnit.Framework.Assert))
if (assem.FullName.ToLowerInvariant().StartsWith("nunit.framework"))
{
_runningFromNUnit = true;
break;
}
}
}
public static bool IsRunningFromNUnit
{
get { return _runningFromNUnit; }
}
}
Run Code Online (Sandbox Code Playgroud)
在后面管道我们都是足够大的男孩,当我们做某事时我们可能不应该认识到;)
dan*_*gph 55
改编自Ryan的答案.这个是针对MS单元测试框架的.
我需要这个的原因是因为我在错误上显示MessageBox.但我的单元测试也测试了错误处理代码,我不想在运行单元测试时弹出MessageBox.
/// <summary>
/// Detects if we are running inside a unit test.
/// </summary>
public static class UnitTestDetector
{
static UnitTestDetector()
{
string testAssemblyName = "Microsoft.VisualStudio.QualityTools.UnitTestFramework";
UnitTestDetector.IsInUnitTest = AppDomain.CurrentDomain.GetAssemblies()
.Any(a => a.FullName.StartsWith(testAssemblyName));
}
public static bool IsInUnitTest { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
这是一个单元测试:
[TestMethod]
public void IsInUnitTest()
{
Assert.IsTrue(UnitTestDetector.IsInUnitTest,
"Should detect that we are running inside a unit test."); // lol
}
Run Code Online (Sandbox Code Playgroud)
Jür*_*ock 18
我使用类似的方法作为高度
这是可以轻松修改以包含缓存的基本代码.另一个好主意是添加一个setter IsRunningInUnitTest并调用UnitTestDetector.IsRunningInUnitTest = false你的项目主入口点以避免代码执行.
public static class UnitTestDetector
{
public static readonly HashSet<string> UnitTestAttributes = new HashSet<string>
{
"Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute",
"NUnit.Framework.TestFixtureAttribute",
};
public static bool IsRunningInUnitTest
{
get
{
foreach (var f in new StackTrace().GetFrames())
if (f.GetMethod().DeclaringType.GetCustomAttributes(false).Any(x => UnitTestAttributes.Contains(x.GetType().FullName)))
return true;
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
cdi*_*ins 18
简化Ryan的解决方案,您只需将以下静态属性添加到任何类:
public static readonly bool IsRunningFromNUnit =
AppDomain.CurrentDomain.GetAssemblies().Any(
a => a.FullName.ToLowerInvariant().StartsWith("nunit.framework"));
Run Code Online (Sandbox Code Playgroud)
Kiq*_*net 11
也许有用,检查当前ProcessName:
public static bool UnitTestMode
{
get
{
string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
return processName == "VSTestHost"
|| processName.StartsWith("vstest.executionengine") //it can be vstest.executionengine.x86 or vstest.executionengine.x86.clr20
|| processName.StartsWith("QTAgent"); //QTAgent32 or QTAgent32_35
}
}
Run Code Online (Sandbox Code Playgroud)
此功能也应通过unittest检查:
[TestClass]
public class TestUnittestRunning
{
[TestMethod]
public void UnitTestRunningTest()
{
Assert.IsTrue(MyTools.UnitTestMode);
}
}
Run Code Online (Sandbox Code Playgroud)
参考文献:
Matthew Watson在http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/11e68468-c95e-4c43-b02b-7045a52b407e/
在测试模式下,Assembly.GetEntryAssembly()似乎是null.
#IF DEBUG // Unit tests only included in debug build
if (Assembly.GetEntryAssembly() == null)
{
// Do some setup to avoid error
}
#endif
Run Code Online (Sandbox Code Playgroud)
请注意,如果Assembly.GetEntryAssembly()是null,Assembly.GetExecutingAssembly()则不是.
该文件说:该GetEntryAssembly方法可以返回null时,管理组件已经从非托管应用程序加载.
正在测试的项目中的某个地方:
public static class Startup
{
public static bool IsRunningInUnitTest { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在您的单元测试项目中的某个地方:
[TestClass]
public static class AssemblyInitializer
{
[AssemblyInitialize]
public static void Initialize(TestContext context)
{
Startup.IsRunningInUnitTest = true;
}
}
Run Code Online (Sandbox Code Playgroud)
优雅,没有.但是直截了当,快速.AssemblyInitializer用于MS测试.我希望其他测试框架具有等价物.
小智 5
只需使用这个:
AppDomain.CurrentDomain.IsDefaultAppDomain()
Run Code Online (Sandbox Code Playgroud)
在测试模式下,它将返回 false。