C# 有没有一种方法可以断言代码块不';不编译?

C# 有没有一种方法可以断言代码块不';不编译?,c#,mstest,assert,C#,Mstest,Assert,在MS测试中,有没有一种方法可以断言代码块不可编译?假设我有一个对象,我想成为一个单身汉。我可能想确保这个对象没有公共构造函数。有没有办法做到这一点 Action create = { new Logger("abc.txt") }; Assert.CompilerError(create); 我可以使用反射来实现这一点,但我很好奇是否有办法断言代码实际上没有编译。下面是我如何使用反射来实现这一点: [TestMethod] public void OnlyPrivateConstructor

在MS测试中,有没有一种方法可以断言代码块不可编译?假设我有一个对象,我想成为一个单身汉。我可能想确保这个对象没有公共构造函数。有没有办法做到这一点

Action create = { new Logger("abc.txt") };
Assert.CompilerError(create);
我可以使用反射来实现这一点,但我很好奇是否有办法断言代码实际上没有编译。下面是我如何使用反射来实现这一点:

[TestMethod]
public void OnlyPrivateConstructors()
{
    var flags = (System.Reflection.BindingFlags)int.MaxValue; //all flags
    var constructors = typeof(Logger).GetConstructors(flags);

    foreach (var item in constructors)
    {
        Assert.IsTrue(item.IsPrivate);
    }
}

MS测试运行编译后的代码。如果代码没有编译,它就不能被测试

您可以用Roslyn创建一个带有相关代码块的字符串,然后让Roslyn编译它

在roslyn之前,您可以创建一个包含代码块的文件,然后使用System.Diagnostics.Process或类似工具对其运行csc,但这会带来更多麻烦

我会坚持使用反射,但由于内部或受保护的构造函数也会允许违反单例模式,因此我将
Assert.IsTrue(item.IsPrivate)


我还需要测试
Assert.IsTrue(typeof(Logger.IsSealed)
。我想是有点像皮带和吊带,但就是这样。

我觉得你把反射代码弄得太复杂了。这将以更少的工作量获得相同的结果,但正如前面提到的那样,您无法编译无法编译的代码


您可以使用CSharpCodeProvider尝试动态编译代码,但正如Phoog所说,这可能会带来更多麻烦:

        var compiler = new CSharpCodeProvider();

        string source = "using DLLBeingTested; \r\n" +
                        "public class DoIt {\r\n" +
                        "public void DoSomething() {\r\n" +
                        "var x =  new Logger(\"abc.txt\");\r\n" +
                        "}}" +
                        "";

        var loc = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);


        var cp = new CompilerParameters(new[] { Path.Combine(loc, "DLLBeingTested.dll") });
        cp.ReferencedAssemblies.Add("System.dll");
        cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");

        var assm = compiler.CompileAssemblyFromSource(cp, source);

        bool foundExpectedError = false;
        foreach (var err in assm.Errors)
        {
            if (err.ToString().Contains("CS0143"))
            {
                foundExpectedError = true;
            }
        }

        Assert.IsTrue(foundExpectedError);

+1用于硬核单元测试。不,没有。也许你应该考虑创建一个单身汉。拥有一个单例测试与单元测试相反。我正在逐步阅读一个TDD教程,它使用一个单例测试。它断言Cannon的两个实例引用同一个对象,但我认为如果开发人员无意中拥有一个公共Cannon构造函数,那么该测试就会失败。在我的帖子中,我使用了Logger类,因为我认为Logger类是singleton的原型。@user2023861您是对的。在本例中,使默认Cannon构造函数私有将强制重写测试。如果以后有人将构造函数更改回public,那么似乎没有一个测试会失败。如果我是你,我会使用你在问题中概述的反射方法。@user2023861我会
Assert.IsTrue(item.IsPrivate)
,但是,因为受保护或内部构造函数也会允许违反单例模式。根据绑定标志,GetConstructors还会返回私有构造函数。我不知道如何让它只返回非私有构造函数。在Roslyn之前,正如我在回答中所解释的,有CSharpCodeProvider,但我确实同意这可能比它的价值更麻烦。@JohnKoerner感谢您指出这一点,并对您的回答加1。我对CSharpCodeProvider有一些模糊的想法,但我没有去追求,因为(再次)这似乎比它的价值更麻烦。
        var compiler = new CSharpCodeProvider();

        string source = "using DLLBeingTested; \r\n" +
                        "public class DoIt {\r\n" +
                        "public void DoSomething() {\r\n" +
                        "var x =  new Logger(\"abc.txt\");\r\n" +
                        "}}" +
                        "";

        var loc = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);


        var cp = new CompilerParameters(new[] { Path.Combine(loc, "DLLBeingTested.dll") });
        cp.ReferencedAssemblies.Add("System.dll");
        cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");

        var assm = compiler.CompileAssemblyFromSource(cp, source);

        bool foundExpectedError = false;
        foreach (var err in assm.Errors)
        {
            if (err.ToString().Contains("CS0143"))
            {
                foundExpectedError = true;
            }
        }

        Assert.IsTrue(foundExpectedError);