如何避免或跳过XUnit测试的一些私有方法



假设我已经编写了一个单元测试来测试XUnit中的公共方法。

[Fact]
public void MethodA_WhenSomething_ThenReturnNull()
{
// Code removed for brevity.
// Assert
}

这是MethodA。

public void MethodA() {
MethodOne();
MethodTwo();
MethodThree();
}

MethodOne、MethodTwo和MethodTree都是私有方法。在为MethodA运行单元测试时,有没有办法跳过私有方法(即MethodTwo(?我想跳过methodTwo的原因是methodTwo调用了一个存储过程,并导致Xuit出错。但我知道存储过程运行良好,没有问题,所以我可以跳过这个方法。

现在,我正在用这种方式。

public void MethodA() {
MethodOne();
#if DEBUG == false
MethodTwo();
#endif
MethodThree();
}

如果有更好的方法,我不想放If DEBUG

这类问题通常通过Moq.Protected解决。

因此,至少对于MethodTwo,您需要将private访问器更改为protected
但我建议将所有访问者更改为protected

public class SomeClass
{
public void MethodA()
{
MethodOne();
MethodTwo();
MethodThree();
}
protected void MethodOne() { ... }
protected void MethodTwo() { ... }
protected void MethodThree() { ... }
}

有了这个,模拟设置将如下所示:

using Moq.Protected;
...
var mockSomeClass = new Mock<SomeClass>();
mockSomeClass.Protected()
.Setup("MethodTwo")
.Verifiable();

此外,您可以设置一个Callback来编写测试输出

const string toBeMockedMethodName = "MethodTwo";
mockSomeClass.Protected()
.Setup(toBeMockedMethodName)
.Callback(() => TestContext.Progress.Writeline($"{toBeMockedMethodName} has been called."))
.Verifiable();

参考文献:

  • 嘲笑受保护的成员
  • 受保护的成员-C中的单元测试#
  • Moq-如何用无参数构造函数模拟内部类的受保护方法

如果您的私有方法依赖于某个外部服务,那么您可以创建一个mock并将其标记为可验证。

[Fact]
public void MethodA_WhenSomething_ThenReturnNull()
{
var barService = new Mock<Bar>();
barService.Setup(x => x.DoSomething()).Verifiable();
///
}
public class Foo
{
public void MethodA()
{
MethodOne();
MethodTwo();
MethodThree();
}
private void MethodThree() => System.Console.WriteLine();
private void MethodTwo() => new Bar().DoSomething();
private void MethodOne() => System.Console.WriteLine();

}
public class Bar
{
public void DoSomething() => System.Console.WriteLine("....");
}

有几种方法可以用来替换私有方法。让我们使用MethodRedirect库。

假设有以下类:

public class SomeClass
{
public void MethodA()
{
MethodOne();
MethodTwo();
MethodThree();
}
private void MethodOne() { }
private void MethodTwo() =>
throw new NotImplementedException();
private void MethodThree() { }
}
var sc = new SomeClass();
sc.MethodA(); // An exception will be thrown here.

上面的库没有nuget包。因此,我们只需从源中复制三个文件:Extension.cs、MethodOperation.cs和MethodToken.cs。

然后编写以下单元测试:

[Fact]
public void MethodA_WhenCalled_NotThrow()
{
var sut = new SomeClass();
var fake = new Fake();
MethodInfo privateMethod = sut.GetType().GetMethod("MethodTwo", BindingFlags.Instance | BindingFlags.NonPublic);
MethodInfo redirectMethod = fake.GetType().GetMethod("Redirect", BindingFlags.Static | BindingFlags.NonPublic);
var token = privateMethod.RedirectTo(redirectMethod);
sut.MethodA(); // should not throw
token.Restore();
}

其方法将用作替代的辅助类

public class Fake
{
static void Redirect() { }
}

相关内容

  • 没有找到相关文章

最新更新