当使用.Net Core框架编译时,最新的xunit框架不允许库代码中的测试运行器(这适用于普通的Visual Studio代码)。解决方案是创建一个单独的测试项目来运行测试用例。
我遇到的问题是我想测试的一些方法是私有的'方法。 如何从我的测试项目中调用这些方法而不使其范围公开'公众
更一般的问题是:当使用私有方法的公共方法无法使用时,如何测试私有方法?(因为它具有交互性 - 也就是说,它有一个ReadLine ();包含在其中)
可能的解决方案:
1)将私有方法公开,并以某种方式重命名它们,以表明它们不应在外部使用。 (使用'私人'或'内部'作为名称的一部分)
2)创建一个' public static bool Testflag'可以设置为true的字段,以绕过公共方法的交互部分,以确保测试其所有部分。
(虽然我已经使用了上述两种方法 - 我真的不喜欢它,因为私有方法应该保持私有,而标志会增加许多额外的复杂性。有人遇到了同样的问题吗?你是怎么解决的?
答案 0 :(得分:15)
快速解决方案是让private
成员要测试internal
。
然后,您可以将InternalsVisibleTo
属性添加到主库的AssemblyInfo.cs中。这将允许您的测试库(没有其他库,没有反射)访问主库中的内部方法/类。
e.g。
[assembly: InternalVisibleTo("Library.Tests")]
答案 1 :(得分:1)
对于测试内部类,@Patric's answer是正确的。
据说,私有方法是私有的,这有充分的理由。同样,它们也不应成为内部原因,这是有充分理由的。
(还有一些人认为我们不应该为私有方法编写单元测试。为什么?好吧,因为它们是“私有”的!但是如果您真的很认真地为私有方法编写单元测试:)
这是测试私有方法的更好方法:
public class Hello
{
private string _firstName { get; set; }
private string _lastName { get; set; }
public Hello(string firstName, string lastName)
{
_firstName = firstName;
_lastName = lastName;
}
public string HelloMan()
{
if (string.IsNullOrEmpty(_firstName))
throw new Exception("Missing First Name.");
return this.HelloMan(_firstName, _lastName);
}
private string HelloMan(string firstName, string lastName)
{
return $"Hello {firstName} {lastName}!";
}
}
测试过程如下:
public class HelloTests
{
[Fact]
public void PrivateHelloManShouldBeWellFormated()
{
// Arrange
var firstName = "John";
var lastName = "Doe";
Type type = typeof(Hello);
var hello = Activator.CreateInstance(type, firstName, lastName);
MethodInfo method = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(x => x.Name == "HelloMan" && x.IsPrivate)
.First();
//Act
var helloMan = (string)method.Invoke(hello, new object [] {firstName, lastName});
//Assert
helloMan
.Should()
.StartWith("Hello")
.And
.EndWith("!")
.And
.Contain("John")
.And
.Contain("Doe");
}
}
参考:
答案 2 :(得分:1)
如果您需要测试私有方法,那么您就是代码异味。您应该检查您的体系结构,而没有理由要测试私有属性或方法。如果您需要此方法-它不是私有方法,而是另一个类的公共方法。
答案 3 :(得分:0)
老式的逐步改进使得对实用主义者(如果不是纯粹主义者)测试私有方法很有用。
将@Tohid最佳答案再进一步一步,该类可用于调用静态或实例私有方法
public static class TestPrivate
{
public static T StaticMethod<T>(Type ClassType, string Method, object[] CallParams)
{
MethodInfo method = ClassType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
.Where(x => x.Name == Method && x.IsPrivate)
.First();
T output = (T)method.Invoke(null, CallParams);
return output;
}
public static T InstanceMethod<T>(object instance, string Method, object[] CallParams)
{
Type ClassType = instance.GetType();
MethodInfo method = ClassType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(x => x.Name == Method && x.IsPrivate)
.First();
T output = (T)method.Invoke(instance, CallParams);
return output;
}
}
然后按以下方式使用:
{
var result = TestPrivate.InstanceMethod<bool>(InstanceOfClass, "privateMethod", new object[] { param1, param2 });
Assert.True(result);
var actual = TestPrivate.StaticMethod<myReturnType>(typeof(StaticClass), "privateMethod", new object[] { param1, param2, param3 });
Assert.True(actual.prop == expected.prop);
}