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