如何在 C# 中模拟 PrivateObject
How to mock PrivateObject in C#
我有这个代码:
[TestMethod]
public void TestMethod()
{
TextBox txtBox= new TextBox() { Text = "Test" };
PrivateObject privateObj= new PrivateObject(someObject);
var mockObj = new Mock<PrivateObject>();
mockObj.Setup(x => x.Invoke("SomeMethod", It.IsAny<string>())).Returns(true);
object result = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty);
Assert.AreEqual(txtBox.Text, string.Empty);
}
方法"DoSomething"调用了"SomeMethod"方法,其中returns是布尔类型。我怎样才能模拟 SometMetod,以便当我调用它时,他 returns 我需要什么?
抱歉,我应该更彻底地调查您的问题。我没有意识到 PrivateObject
是 .NET 框架中已经存在的 class。
我的回答不会直接回答你的问题,但无论如何我都会把它留在这里。我假设您使用 Moq,因此 classes 的以下部分不可用于模拟:
- 非虚拟成员
- 静态成员
- 扩展方法
- 密封classes
的任何成员
- 字段
私有成员可以测试,我不是说一般都是错的。不过,通常需要测试私有成员是错误代码设计的标志。
私有方法和字段是实现细节,不应影响您的 class 功能。不要将每个方法视为一个单元,而是将 class 视为一个单元。测试你的 class' 行为 并且它做了它应该做的事情而不是测试 它是如何做的。
对象结果 = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty);
您在 privateObj
上调用 DoSomething
方法,而不是在 mockObj
上调用 未设置 到 return 您 "need".
你的单元测试应该实现什么? 被测系统的模拟行为有点矛盾,因为测试结果不能代表系统的实际行为。
我想你可以做的是将 SomeMethod
的功能从 PrivateObject
中提取到它的依赖项中,比方说 IHaveSomeMethod
.
public interface IHaveSomeMethod {
bool SomeMethod();
}
public class PrivateObject {
private IHaveSomeMethod dependency;
public PrivateObject(???SomeObject someObject???, IHaveSomeMethod ihsm) {
// ...
this.iHaveSomeMethod = ihsm;
// ...
}
public void DoSometing() {
// ...
iHaveSomeMethod.SomeMethod();
// ...
}
}
那你可以这样测试
[TestMethod]
public void TestMethod()
{
TextBox txtBox= new TextBox() { Text = "Test" };
var mockObj = new Mock<IHaveSomeMethod>();
mockObj.Setup(x => x.Invoke("SomeMethod", It.IsAny<string>())).Returns(true);
var sut = new PrivateObject(???someObject???, mockObj.Object); // system under test
object result = sut.Invoke("DoSomething", txtBox, EventArgs.Empty);
Assert.AreEqual(txtBox.Text, string.Empty);
}
我有这个代码:
[TestMethod]
public void TestMethod()
{
TextBox txtBox= new TextBox() { Text = "Test" };
PrivateObject privateObj= new PrivateObject(someObject);
var mockObj = new Mock<PrivateObject>();
mockObj.Setup(x => x.Invoke("SomeMethod", It.IsAny<string>())).Returns(true);
object result = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty);
Assert.AreEqual(txtBox.Text, string.Empty);
}
方法"DoSomething"调用了"SomeMethod"方法,其中returns是布尔类型。我怎样才能模拟 SometMetod,以便当我调用它时,他 returns 我需要什么?
抱歉,我应该更彻底地调查您的问题。我没有意识到 PrivateObject
是 .NET 框架中已经存在的 class。
我的回答不会直接回答你的问题,但无论如何我都会把它留在这里。我假设您使用 Moq,因此 classes 的以下部分不可用于模拟:
- 非虚拟成员
- 静态成员
- 扩展方法
- 密封classes 的任何成员
- 字段
私有成员可以测试,我不是说一般都是错的。不过,通常需要测试私有成员是错误代码设计的标志。
私有方法和字段是实现细节,不应影响您的 class 功能。不要将每个方法视为一个单元,而是将 class 视为一个单元。测试你的 class' 行为 并且它做了它应该做的事情而不是测试 它是如何做的。
对象结果 = privateObj.Invoke("DoSomething", txtBox, EventArgs.Empty);
您在 privateObj
上调用 DoSomething
方法,而不是在 mockObj
上调用 未设置 到 return 您 "need".
你的单元测试应该实现什么? 被测系统的模拟行为有点矛盾,因为测试结果不能代表系统的实际行为。
我想你可以做的是将 SomeMethod
的功能从 PrivateObject
中提取到它的依赖项中,比方说 IHaveSomeMethod
.
public interface IHaveSomeMethod {
bool SomeMethod();
}
public class PrivateObject {
private IHaveSomeMethod dependency;
public PrivateObject(???SomeObject someObject???, IHaveSomeMethod ihsm) {
// ...
this.iHaveSomeMethod = ihsm;
// ...
}
public void DoSometing() {
// ...
iHaveSomeMethod.SomeMethod();
// ...
}
}
那你可以这样测试
[TestMethod]
public void TestMethod()
{
TextBox txtBox= new TextBox() { Text = "Test" };
var mockObj = new Mock<IHaveSomeMethod>();
mockObj.Setup(x => x.Invoke("SomeMethod", It.IsAny<string>())).Returns(true);
var sut = new PrivateObject(???someObject???, mockObj.Object); // system under test
object result = sut.Invoke("DoSomething", txtBox, EventArgs.Empty);
Assert.AreEqual(txtBox.Text, string.Empty);
}