在MS Test中,有没有办法断言代码块没有编译?让我们说我有一个对象,我想成为一个单身人士。我可能想确保此对象没有公共构造函数。有没有办法做这样的事情?
Action create = { new Logger("abc.txt") };
Assert.CompilerError(create);
我可以使用Reflection来做到这一点,但我很好奇是否有一种断言代码实际编译的方法。以下是使用Reflection进行此操作的方法:
[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);
}
}
答案 0 :(得分:2)
MS测试运行编译代码。如果代码没有编译,则无法进行测试。
你可以通过创建一个包含相关代码块的字符串,然后让Roslyn编译它来为Roslyn做到这一点。
http://msdn.microsoft.com/en-us/vstudio/roslyn.aspx
Pre-roslyn,您可以创建一个包含代码块的文件,然后使用System.Diagnostics.Process等对它运行csc,但这比它的价值更麻烦。
我会坚持反思,但由于内部或受保护的构造函数也允许违反单例模式,我会Assert.IsTrue(item.IsPrivate)
。
我也会对Assert.IsTrue(typeof(Logger).IsSealed)
进行测试。我想,有点腰带和吊带裤,但就在那里。
答案 1 :(得分:1)
您可以使用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);
答案 2 :(得分:0)
我认为您使反射代码过于复杂。这样可以获得相同的结果而且工作少得多,但正如phoog
提到的那样,您无法编译不会编译的代码。
[TestMethod]
public void NoPrivateConstructors()
{
Assert.IsFalse(typeof(Logger).GetConstructors(/* binding flags... */).Any());
}