Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这些单例单元测试是否真的像预期的那样工作?_C#_Singleton_Xunit_Ncrunch - Fatal编程技术网

C# 这些单例单元测试是否真的像预期的那样工作?

C# 这些单例单元测试是否真的像预期的那样工作?,c#,singleton,xunit,ncrunch,C#,Singleton,Xunit,Ncrunch,我有一个引导程序对象,我正在尝试测试(使用xunit)。测试似乎通过了,但我在我使用的一个测试运行程序(ncrunch)中看到了一些奇怪的东西。我使用ncrunch和resharper-xunit运行程序。我的想法是获取singleton所在的程序集,将其加载到新的appdomain中,使用反射运行测试,然后卸载appdomain。正如我所说,测试在ncrunc和resharper中都通过了,但是ncrunc没有显示我所期望的执行路径。代码如下: public class Bootstrappe

我有一个引导程序对象,我正在尝试测试(使用xunit)。测试似乎通过了,但我在我使用的一个测试运行程序(ncrunch)中看到了一些奇怪的东西。我使用ncrunch和resharper-xunit运行程序。我的想法是获取singleton所在的程序集,将其加载到新的appdomain中,使用反射运行测试,然后卸载appdomain。正如我所说,测试在ncrunc和resharper中都通过了,但是ncrunc没有显示我所期望的执行路径。代码如下:

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);
    }
}
公共类引导程序
{
私有静态引导程序启动;
公共引导程序()
{
//执行引导任务
}
公共静态void Boot()
{
如果(启动==null)
{
var staticboot=new Bootstrapper();
Booted=staticboot;
}
}
公共静态引导程序已启动
{
得到
{
if(booted==null)抛出新的InvalidOperationException(“应该在访问引导对象之前调用Boot());
返回引导;
}
设置{booted=value;}
}
}
公开课考试
{
[事实]
尝试访问启动的KernelBeforoRetoothRowsException()的公共无效
{
var setup=this.SetupTestingDomainWithAssembly(“StackOverflowQuestion.Tests.dll”);
var kernelType=setup.Item2.GetType(“StackOverflowQuestion.Tests.Bootstrapper”);
var bootedkernelProperty=kernelType.GetProperty(“Booted”);
尝试
{
bootedkernelProperty.GetValue(null);
}
捕获(例外e)
{
IsType(typeof(InvalidOperationException),例如InnerException);
}
卸载(setup.Item1);
}
[事实]
public void可以访问启动后的内核()
{
var setup=this.SetupTestingDomainWithAssembly(“StackOverflowQuestion.Tests.dll”);
var kernelType=setup.Item2.GetType(“StackOverflowQuestion.Tests.Bootstrapper”);
var bootMethod=kernelType.GetMethod(“Boot”);
Invoke(null,新对象[]{});
var bootedkernelProperty=kernelType.GetProperty(“Booted”);
Assert.DoesNotThrow(()=>bootedkernelProperty.GetValue(null));
卸载(setup.Item1);
}
[事实]
公共无效bootisdemponent()
{
var setup=this.SetupTestingDomainWithAssembly(“StackOverflowQuestion.Tests.dll”);
var kernelType=setup.Item2.GetType(“StackOverflowQuestion.Tests.Bootstrapper”);
var bootMethod=kernelType.GetMethod(“Boot”);
Invoke(null,新对象[]{});
var bootedkernelProperty=kernelType.GetProperty(“Booted”);
var bootedKernel=(Bootstrapper)bootedkernelProperty.GetValue(null);
Invoke(null,新对象[]{});
var secondCall=(引导程序)bootedkernelProperty.GetValue(null);
相等(bootedKernel,secondCall);
卸载(setup.Item1);
}
私有元组设置TestingDomainWithAssembly(字符串assemblyPath)
{
//我们保证每个域都有一个唯一的名称。
AppDomain testingDomain=AppDomain.CreateDomain(DateTime.Now.Ticks.ToString());
var pancakesAssemblyName=new AssemblyName();
PancakesSemblyName.CodeBase=assemblyPath;
var assembly=testingDomain.Load(pancakesAssemblyName);
返回新元组(testingDomain、assembly);
}
}
现在,我认识到需要在代码方面进行一些清理,但我很高兴看到它们都是绿色的。如果我摆弄他们,让他们失败,那是意料之中的事。唯一有点难闻的是ncrunch报告了奇怪的执行路径。具体地说,ncrunch表示抛出无效操作异常的行永远不会执行

我想ncrunch在处理其他应用程序域时可能有一个bug,但更可能的是,我并不真正了解应用程序域的情况,但我不确定从这里继续到哪里


另外,我确实知道单身是不好的,但我相信引导者是他们真正有用的地方。你要保证它们只启动一次。

除非我这里遗漏了什么。。看起来你实际上并没有调用其他应用程序域中的任何内容。您的反射正在当前应用程序域中发生。请看DoCallback方法:


好的,是的,你是对的。这比我想象的要复杂得多。我得重新考虑一下。
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;
    }
}