我有一个我试图测试的引导程序对象(使用xunit)。测试似乎已经过去了,但我在其中一个测试跑步者(ncrunch)中看到了一些奇怪的东西。我同时使用ncrunch和resharper xunit runner。我的想法是采用单例所在的程序集,将其加载到新的appdomain中,使用反射运行我的测试,然后卸载app域。正如我所说,测试传递了ncrunch和resharper,但是ncrunch没有显示我期望的执行路径。这是代码:
public class Bootstrapper
{
private static Bootstrapper booted;
public Bootstrapper()
{
// performs boot tasks
}
public static void Boot()
{
if (booted == null)
{
var staticboot = new Bootstrapper();
Booted = staticboot;
}
}
public static Bootstrapper Booted
{
get
{
if (booted == null) throw new InvalidOperationException("Should call Boot() before accessing the booted object");
return booted;
}
set { booted = value; }
}
}
public class Tests
{
[Fact]
public void TryingToAccessBootedKernelBeforeBootThrowsException()
{
var setup = this.SetupTestingDomainWithAssembly("StackOverflowQuestion.Tests.dll");
var kernelType = setup.Item2.GetType("StackOverflowQuestion.Tests.Bootstrapper");
var bootedkernelProperty = kernelType.GetProperty("Booted");
try
{
bootedkernelProperty.GetValue(null);
}
catch (Exception e)
{
Assert.IsType(typeof(InvalidOperationException), e.InnerException);
}
AppDomain.Unload(setup.Item1);
}
[Fact]
public void CanAccessKernelAfterBooting()
{
var setup = this.SetupTestingDomainWithAssembly("StackOverflowQuestion.Tests.dll");
var kernelType = setup.Item2.GetType("StackOverflowQuestion.Tests.Bootstrapper");
var bootMethod = kernelType.GetMethod("Boot");
bootMethod.Invoke(null, new object[] { });
var bootedkernelProperty = kernelType.GetProperty("Booted");
Assert.DoesNotThrow(() => bootedkernelProperty.GetValue(null));
AppDomain.Unload(setup.Item1);
}
[Fact]
public void BootIsIdempotent()
{
var setup = this.SetupTestingDomainWithAssembly("StackOverflowQuestion.Tests.dll");
var kernelType = setup.Item2.GetType("StackOverflowQuestion.Tests.Bootstrapper");
var bootMethod = kernelType.GetMethod("Boot");
bootMethod.Invoke(null, new object[] {});
var bootedkernelProperty = kernelType.GetProperty("Booted");
var bootedKernel = (Bootstrapper)bootedkernelProperty.GetValue(null);
bootMethod.Invoke(null, new object[] {});
var secondCall = (Bootstrapper)bootedkernelProperty.GetValue(null);
Assert.Equal(bootedKernel, secondCall);
AppDomain.Unload(setup.Item1);
}
private Tuple<AppDomain, Assembly> SetupTestingDomainWithAssembly(string assemblyPath)
{
// we guarantee that each domain will have a unique name.
AppDomain testingDomain = AppDomain.CreateDomain(DateTime.Now.Ticks.ToString());
var pancakesAssemblyName = new AssemblyName();
pancakesAssemblyName.CodeBase = assemblyPath;
var assembly = testingDomain.Load(pancakesAssemblyName);
return new Tuple<AppDomain, Assembly>(testingDomain, assembly);
}
}
现在,我认识到需要在代码方面进行一些清理,但我很高兴看到它们都是绿色的。如果我摆弄它们使它们失败,那就按预期工作了。唯一有点臭的是,ncrunch报告了奇怪的执行路径。具体来说,ncrunch表明从不执行抛出无效操作异常的行。
我认为在处理其他应用程序域时,ncrunch可能存在错误,但我更有可能实际上不了解应用程序域的内容,但我不确定从何处继续这里。
另外,我确实知道单身人士很糟糕,但我相信bootstrappers是他们实际上有用的地方。你想保证它们只被启动一次。
答案 0 :(得分:1)
除非我在这里遗漏了一些东西......看起来你实际上并没有在你的其他app域中调用任何东西。您的反映发生在当前的应用领域。看一下DoCallback方法:http://msdn.microsoft.com/en-us/library/system.appdomain.docallback.aspx
public class Tests
{
[Fact]
public void TryingToAccessBootedKernelBeforeBootThrowsException()
{
var appDomain = AppDomain.Create(Guid.NewGuid());
try
{
appDomain.DoCallBack(new CrossAppDomainDelegate(TryingToAccessBootedKernelBeforeBootThrowsException_AppDomainCallback));
}
catch (Exception e)
{
Assert.IsType(typeof(InvalidOperationException), e.InnerException);
}
AppDomain.Unload(appDomain);
}
public static void TryingToAccessBootedKernelBeforeBootThrowsException_AppDomainCallback()
{
var bootstrapper = BootStrapper.Booted;
}
}