使用 FakeItEasy 模拟私有方法
Mock private methods using FakeItEasy
我已经实现了使用 FakeItEasy Framework 模拟测试 public 虚拟方法的解决方案。下面我有一个带有私有方法的测试 class,私有方法不能是虚拟的。所以请帮助我使用 FakeItEasy Framework
模拟 Private 方法
Class待测
public class XYZ
{
public static int nValue = 0;
private void AddInetegers()
{
int i = 3;
int j = i * 100;
int k = j * 30 / 100;
Show(String.Format("Value Here {0}", k.ToString()));
nValue = k;
}
public virtual void Show(string message)
{
MessageBox.Show(message);
}
}
测试Class
[TestMethod]
public void Test_Using_FakeItEasy()
{
var instance = A.Fake<XYZ>();
A.CallTo(() => instance.Show("Hello"));
//A.CallTo(() => instance.AddInetegers(3)).CallsBaseMethod();
A.CallTo(instance).Where(x => x.Method.Name.Contains("AddInetegers")).MustHaveHappened();
Assert.AreEqual(90, XYZ.nValue);
}
错误:
Result Message: Test method PrjMSTest.Test.Test_Using_FakeItEasy
threw exception: FakeItEasy.ExpectationException:
Assertion failed for the following call:
Any call made to the fake object.
where x => x.Method.Name.Contains("AddInetegers")
Expected to find it at least once but no calls were made to the fake object.
正如他们在评论中告诉您的那样,您无法轻易测试私有方法,而且在绝大多数情况下,您可能不应该这样做。
如果出于某种原因,您仍想测试 AddInetegers()
,可以使用 "dirty" 方法来隐藏某种信息并测试您的方法。
首先,你必须AddInetegers
内部;它在您的程序集之外是不可见的,您将能够对其进行测试。
然后找到你的XYZ
class所属项目的Properties\AssemblyInfo.cs文件;假设你的项目名为 MyProject
而你的测试项目是 MyProjectTests
,你可以添加
using System.Runtime.CompilerServices;
到 AssemblyInfo.cs 和
的顶部
[assembly: InternalsVisibleTo("MyProjectTests")]
到底部。这将使您的方法可测试。更多信息 here or here.
然后还有一种更肮脏的方法,即将您的方法保密;它被提到例如here or here and relies on PrivateObject
, which has been around since 2004 as per this article 詹姆斯·纽柯克本人
var CurrentInstance = new XYZ();
var PrivateObject= new PrivateObject(CurrentInstance);
PrivateObject.Invoke("AddInetegers");
Assert.AreEqual(90, XYZ.nValue);
老实说,除非您正在处理非常复杂的遗留代码,否则您可能想利用您的设计技能并考虑为什么要测试一个私有方法以及为什么它的作者决定将其私有化。
This answer 非常详尽地说明了为什么您不应该测试私有方法 and/or 为什么您要测试的那些方法不应该是私有的。
但它也解释了为什么您可能需要这样做:
- 重构时 and/or 向可能您还没有时间熟悉的旧系统添加测试
sometimes it is simply safest to just test the private functionality
- 当有人给你一个不合理的截止日期时
You're in a rush, and have to do the fastest thing possible for here
and now. In the long run, you don't want to test private methods. But
I will say that it usually takes some time to refactor to address
design issues. And sometimes you have to ship in a week. That's okay:
do the quick and dirty and test the private methods using a groping
tool if that's what you think is the fastest and most reliable way to
get the job done. But understand that what you did was suboptimal in
the long run, and please consider coming back to it (or, if it was
forgotten about but you see it later, fix it).
我已经实现了使用 FakeItEasy Framework 模拟测试 public 虚拟方法的解决方案。下面我有一个带有私有方法的测试 class,私有方法不能是虚拟的。所以请帮助我使用 FakeItEasy Framework
模拟 Private 方法Class待测
public class XYZ
{
public static int nValue = 0;
private void AddInetegers()
{
int i = 3;
int j = i * 100;
int k = j * 30 / 100;
Show(String.Format("Value Here {0}", k.ToString()));
nValue = k;
}
public virtual void Show(string message)
{
MessageBox.Show(message);
}
}
测试Class
[TestMethod]
public void Test_Using_FakeItEasy()
{
var instance = A.Fake<XYZ>();
A.CallTo(() => instance.Show("Hello"));
//A.CallTo(() => instance.AddInetegers(3)).CallsBaseMethod();
A.CallTo(instance).Where(x => x.Method.Name.Contains("AddInetegers")).MustHaveHappened();
Assert.AreEqual(90, XYZ.nValue);
}
错误:
Result Message: Test method PrjMSTest.Test.Test_Using_FakeItEasy threw exception: FakeItEasy.ExpectationException:
Assertion failed for the following call:
Any call made to the fake object.
where x => x.Method.Name.Contains("AddInetegers")
Expected to find it at least once but no calls were made to the fake object.
正如他们在评论中告诉您的那样,您无法轻易测试私有方法,而且在绝大多数情况下,您可能不应该这样做。
如果出于某种原因,您仍想测试 AddInetegers()
,可以使用 "dirty" 方法来隐藏某种信息并测试您的方法。
首先,你必须AddInetegers
内部;它在您的程序集之外是不可见的,您将能够对其进行测试。
然后找到你的XYZ
class所属项目的Properties\AssemblyInfo.cs文件;假设你的项目名为 MyProject
而你的测试项目是 MyProjectTests
,你可以添加
using System.Runtime.CompilerServices;
到 AssemblyInfo.cs 和
的顶部[assembly: InternalsVisibleTo("MyProjectTests")]
到底部。这将使您的方法可测试。更多信息 here or here.
然后还有一种更肮脏的方法,即将您的方法保密;它被提到例如here or here and relies on
PrivateObject
, which has been around since 2004 as per this article 詹姆斯·纽柯克本人
var CurrentInstance = new XYZ();
var PrivateObject= new PrivateObject(CurrentInstance);
PrivateObject.Invoke("AddInetegers");
Assert.AreEqual(90, XYZ.nValue);
老实说,除非您正在处理非常复杂的遗留代码,否则您可能想利用您的设计技能并考虑为什么要测试一个私有方法以及为什么它的作者决定将其私有化。 This answer 非常详尽地说明了为什么您不应该测试私有方法 and/or 为什么您要测试的那些方法不应该是私有的。
但它也解释了为什么您可能需要这样做:
- 重构时 and/or 向可能您还没有时间熟悉的旧系统添加测试
sometimes it is simply safest to just test the private functionality
- 当有人给你一个不合理的截止日期时
You're in a rush, and have to do the fastest thing possible for here and now. In the long run, you don't want to test private methods. But I will say that it usually takes some time to refactor to address design issues. And sometimes you have to ship in a week. That's okay: do the quick and dirty and test the private methods using a groping tool if that's what you think is the fastest and most reliable way to get the job done. But understand that what you did was suboptimal in the long run, and please consider coming back to it (or, if it was forgotten about but you see it later, fix it).