公开私有方法以对其进行单元测试……好主意?


301

主持人注意: 这里已经发布了39个答案(有些已经删除)。 你发布之前你的答案,考虑你是否能添加一些有意义的讨论。您很有可能只是重复别人已经说过的话。


我偶尔会发现自己需要在类中公开一个私有方法,只是为此编写了一些单元测试。

通常这是因为该方法包含该类中其他方法之间共享的逻辑,并且可以更轻松地自行测试该逻辑,或者另一个原因可能是我想测试同步线程中使用的逻辑而不必担心线程问题。

其他人是否发现自己这样做,因为我真的不喜欢这样做?我个人认为,好处超过了公开方法的问题,而该方法实际上并没有提供课堂以外的任何服务。

更新

谢谢大家的回答,似乎引起了人们的兴趣。我认为,普遍的共识是应该通过公共API进行测试,因为这是使用类的唯一方法,我对此表示同意。我在上面提到的几个我在上面会做的情况并不常见,我认为这样做的好处是值得的。

但是,我可以看到每个人都指出,它永远不会真正发生。而且,当我多考虑一下时,我认为更改代码以容纳测试是一个坏主意-毕竟,我认为测试在某种程度上是一种支持工具,并且如果愿意的话,将系统更改为“支持支持工具”是公然的。坏习惯。


2
“如果愿意,将系统更改为'支持支持工具'是公然的不良做法”。好吧,是的。但是OTOH,如果您的系统不能很好地使用已建立的工具,则可能系统出了问题。
Thilo


1
这不是一个答案,但是您始终可以通过反射来访问它们。
Zano

33
不,您不应该公开它们。相反,您应该通过其公共API 测试类的行为。而且,如果公开内部结构确实是唯一的选择(我对此表示怀疑),那么您至少应使accessors程序包受保护,以便只有同一程序包中的类(如您的测试所用)可以访问它们。
JB Nizet 2015年

4
是的。给予方法包私有(默认)可见性以使其可以从单元测试中访问是完全可以接受的。像Guava这样的库甚至都提供了@VisibileForTesting注释来制作这种方法-我建议您这样做,以便private正确记录该方法的原因。
蜘蛛鲍里斯(Boris)

Answers:


186

注意:
此答案最初针对以下问题而发布的单独进行单元测试是否是通过getter公开私有实例变量的充分理由?它已合并到此示例中,因此可能是针对此处显示的用例的一点点。

一般而言,我通常都是为了重构“生产”代码以使其更易于测试。但是,我认为这不是一个好电话。一个好的单元测试(通常)通常不必关心类的实现细节,而只关心其可见行为。不必将内部堆栈暴露给测试,而是可以测试该类在调用first()或之后以您期望的顺序返回页面last()

例如,考虑以下伪代码:

public class NavigationTest {
    private Navigation nav;

    @Before
    public void setUp() {
        // Set up nav so the order is page1->page2->page3 and
        // we've moved back to page2
        nav = ...;
    }

    @Test
    public void testFirst() {
        nav.first();

        assertEquals("page1", nav.getPage());

        nav.next();
        assertEquals("page2", nav.getPage());

        nav.next();
        assertEquals("page3", nav.getPage());
    }

    @Test
    public void testLast() {
        nav.last();

        assertEquals("page3", nav.getPage());

        nav.previous();
        assertEquals("page2", nav.getPage());

        nav.previous();
        assertEquals("page1", nav.getPage());
    }
}

8
我完全同意你的回答。许多开发人员会倾向于使用默认的访问修饰符,并证明良好的开源框架使用此策略是合理的,因此它必须正确。仅仅因为可以做并不意味着你应该做。+1
CKing

6
尽管其他人提供了有用的见解,但我不得不说这是我认为最适合此问题的解决方案。它使测试完全不可知如何在内部实现预期的行为。+10!
Gitahi Ng'ang'a 2015年

顺便说一句,在@Mureinik提供的示例中,测试方法最终涵盖的范围比实际的测试方法还好吗?例如,testFirst()调用next(),这实际上不是被测试的方法,first()是。仅用一种测试方法涵盖所有​​4种导航方法会不会更干净,更清晰?
Gitahi Ng'ang'a

1
尽管这是理想的选择,但有时您需要检查组件是否以正确的方式完成了某些事情,而不仅仅是成功了。这可能很难进行黑盒测试。有时您必须对组件进行白盒测试。
彼得·劳瑞

1
创建吸气剂只是为了进行单元测试?这绝对违背了OOP / Object Thinking的原则,因为接口应该公开行为,而不是数据。
IntelliData

151

就个人而言,我宁愿使用公共API进行单元测试,而且我绝对不会公开私有方法只是为了使其易于测试。

如果您真的想单独测试私有方法,则可以在Java中使用Easymock / Powermock来执行此操作。

您必须对此务实,并且还应该知道难以测试的原因。

' 听测试 '-如果很难测试,这是否告诉您一些有关您的设计的信息?您能否将这种方法的测试重构为琐碎的地方,并通过公共api进行测试轻松覆盖?

这就是迈克尔·费瑟斯(Michael Feathers)在“ 有效地使用旧版代码工作 ”中所说的话

“许多人花费大量时间试图解决这个问题……真正的答案是,如果您有测试专用方法的冲动,则该方法不应是专用的;如果将该方法公开,麻烦您了,可能是因为它是单独职责的一部分;它应该在另一个类上。” [ M. Feathers 有效地使用旧版代码(2005)]


5
为Easymock / Powermock +1,并且永远不要公开私有方法
LeonardBrünings11年

51
+1对于“听测试”。如果您需要测试私有方法,则很有可能该方法中的逻辑非常复杂,以至于应将其放在单独的帮助器类中。然后,您可以测试助手类。
Phil

2
“听测试”似乎已失败。这里是一个高速缓存链接:webcache.googleusercontent.com/...
杰斯德福

1
我同意@Phil(尤其是本书的参考书),但是我经常发现自己在使用遗留代码的情况下陷入困境。我知道此方法属于另一个类,但是如果没有测试,我不是100%愿意进行重构。
凯文

我同意医生的意见。如果需要测试私有方法,则可能应该在另一个类中。您可能会注意到,私有方法可能会变成公共/受保护的另一个类/帮助类。
rupweb

67

就像其他人所说的,完全可以对私有方法进行单元测试。单元测试公共接口,而不是私有实现细节。

就是说,当我要对C#中私有的东西进行单元测试时,我使用的技术是将可访问性保护从私有降级为内部,然后使用InternalsVisibleTo将单元测试程序集标记为朋友程序集。然后将允许单元测试组件将内部零件视为公开零件,但是您不必担心会意外地增加您的公共零件表面积。


我也使用这种技术,但是通常作为遗留代码的最后手段。如果需要测试私有代码,则可能缺少类/正在测试的类做得太多。将所述代码提取到一个新的类中,您可以单独对其进行测试。这样的技巧很少使用。
Finglas

但是,仅提取一个类并进行测试就意味着您的测试会失去对原始类实际上正在使用提取的代码的了解。您如何建议您在测试中填补这一空白?而且如果答案是仅以导致使用提取的逻辑的方式测试原始类的公共接口,那么为什么要一开始就提取它呢?(顺便说一句,我并不是要在这里引起对抗,我一直想知道人们如何平衡这种取舍。)
马尔·罗斯

@mal我要进行协作测试。换句话说,用于验证新类的模拟程序已正确调用。请参阅下面的答案。
Finglas

可以编写一个测试类,该类从您要测试的内部逻辑继承自该类,并提供一种用于测试内部逻辑的公共方法吗?
sholsinger

1
@sholsinger:在C#中,公共类不能从内部类继承。
埃里克·利珀特

45

很多答案都建议仅测试公共接口,但是恕我直言,这是不现实的-如果某个方法执行需要5个步骤的操作,则需要分别测试这五个步骤,而不是一起测试。这需要测试所有五种方法,其中(比其他测试),否则可能会private

测试“私有”方法的通常方法是为每个类提供自己的接口,并创建“私有”方法public,但不将其包括在接口中。这样,它们仍然可以进行测试,但不会使界面过大。

是的,这将导致文件和类膨胀。

是的,这确实使publicprivate说明符变得多余。

是的,这是一个痛苦的屁股。

不幸的是,这是我们使代码可测试的许多牺牲之一。也许将来的语言(甚至是将来的C#/ Java版本)将具有使类和模块可测试性更加方便的功能。但与此同时,我们必须跳过这些障碍。


有些人认为每个步骤都应该是自己的类,但是我不同意-如果它们都共享状态,则没有理由创建五个方法可以做到的五个单独的类。更糟糕的是,这会导致文件和类膨胀。 另外,它会感染您模块的公共API- public如果您要从另一个模块测试它们,那么所有这些类都必须是必需的(要么在同一模块中包含测试代码,要么在同一模块中包含测试代码,这意味着将测试代码与产品一起提供)


2
第一半的好答案
cmcginty 2011年

7
+1:对我来说最好的答案。如果汽车制造商出于相同的原因不对汽车的一部分进行测试,那么我不确定是否有人会购买。即使我们应该将代码的重要部分更改为公开,也应对其进行测试。
泰成新

1
很好的答案。你有我的热情票。我添加了一个答案。您可能会感兴趣。
davidxxx

29

单元测试应该测试公共合同,这是在代码的其他部分中如何使用类的唯一方法。私有方法是实现细节,您不应该对其进行测试,只要公共API正常工作,实现就无关紧要,并且可以在不更改测试用例的情况下进行更改。



Afair,我曾经决定在测试案例中使用私有的罕见情况是,当我验证对象正确性时-如果它已关闭所有JNI处理程序。显然,它没有公开为公共API,但是,如果不发生,则会发生内存泄漏。但是有趣的是,稍后我将内存泄漏检测器作为公共API的一部分引入之后,我也将其消除。

11
这是有缺陷的逻辑。单元测试的重点是早发现错误。通过不测试私有方法,您将在测试中留下一些差距,这些差距可能要等到很久以后才能发现。如果私有方法很复杂且不易于通过公共接口执行,则应进行单元测试。
cmcginty 2011年

6
@Casey:如果私有方法没有被公共接口使用,为什么会存在呢?
Thilo

2
@DaSilva_Ireland:将来很难维护测试用例。唯一的真实类用例是通过public方法。也就是说,所有其他代码只能通过公共API使用该类。因此,如果您要更改实现并且私有方法测试用例失败,这并不意味着您做错了,而且,如果您仅测试私有,而不是完全测试公共,则不会涵盖某些潜在的错误。 。理想情况下,测试用例应涵盖所有可能的情况,并且仅涵盖类实际使用的情况。

22

IMO,您应该编写测试,而不要对您的类在内部的实现方式做深入的假设。您可能希望稍后使用另一个内部模型对其进行重构,但仍要保证与以前的实现相同的保证。

记住这一点,我建议您重点关注测试您的合同是否仍然有效,无论您的班级目前采用哪种内部实现方式。基于属性的公共API测试。


6
我同意重构代码后不需要重写的单元测试会更好。不仅是因为花费了时间,您还需要花费大量时间重写单元测试。一个更重要的原因是,我认为单元测试的最重要目的是重构后代码仍然可以正确运行。如果重构后必须重写所有单元测试,那么您将失去单元测试的好处。
卡巴斯德(Kasperd),2015年

20

如何使其私有化呢?然后,您的测试代码可以看到它(以及包中的其他类),但是仍然对用户隐藏。

但实际上,您不应该测试私有方法。这些是实施细节,而不是合同的一部分。他们所做的所有事情都应该通过调用公共方法来覆盖(如果它们中的代码没有被公共方法执行,则应该执行)。如果私有代码太复杂,则该类可能正在做太多事情并且需要重构。

公开方法是一项重大的承诺。一旦这样做,人们将可以使用它,而您不能再更改它们了。


+1如果你需要测试你的私处你可能缺少的一类
JK。

+1(缺少课程)。很高兴看到其他人不会立即跳入“内部标记”潮流。
Finglas

男孩,我不得不走很长一段路才能找到包裹的私人答案。
比尔K,

17

更新我在许多其他地方为这个问题添加了更扩展,更完整的答案。这可以在我的博客上找到

如果我需要公开进行测试,这通常暗示被测系统未遵循“ 单一职责原则”。因此,应该引入缺少的类。将代码提取到新类中之后,将其公开。现在,您可以轻松进行测试,并且正在遵循SRP。您的其他类只需通过合成来调用此新类。

公开方法/使用语言技巧(例如将代码标记为可见以测试组件)应该永远是最后的选择。

例如:

public class SystemUnderTest
{
   public void DoStuff()
   {
      // Blah
      // Call Validate()
   }

   private void Validate()
   {
      // Several lines of complex code...
   }
}

通过引入验证器对象来重构它。

public class SystemUnderTest
{
    public void DoStuff()
    {
       // Blah
       validator.Invoke(..)
    }
}

现在,我们要做的就是测试验证器是否正确调用。验证的实际过程(以前的专用逻辑)可以在纯隔离中进行测试。无需进行复杂的测试即可确保此验证通过。


1
我个人认为SRP可能太过分了,例如,如果我编写了一个处理应用程序中的更新/创建/删除帐户的帐户服务,您是否告诉我应该为每个操作创建一个单独的类?例如,关于验证,当它永远不会在其他任何地方使用时,将验证逻辑提取到另一个类真的值得吗?imo会使代码的可读性,简洁性降低,并为您的应用程序添加多余的类!
jcvandan 2011年

1
这完全取决于场景。一个人对“做某事”的定义可能与另一个人不同。在这种情况下,对于您自己来说,很明显,您要测试的私人代码很复杂/设置起来很麻烦。您想要测试的事实证明它做得太多。因此,是的,拥有一个新对象将是理想的。
Finglas

1
至于使您的代码可读性差,我非常不同意。与将验证嵌入到另一个对象中相比,拥有用于验证的类更容易阅读。您仍然拥有相同数量的代码,只是没有嵌套在一个大类中。我宁愿有几门课做得很好,而不是一堂大课。
Finglas

4
@dormisher关于您的帐户服务,将SRP视为“更改的唯一原因”。如果您的CRUD操作自然会一起改变,那么它们将适合SRP。通常,您将更改它们,因为数据库架构可能会更改,这自然会影响插入和更新(尽管可能并不总是删除)。
安东尼·佩格拉姆

@finglas您对此有何看法:stackoverflow.com/questions/29354729/…。我不想测试私有方法,所以也许我不应该将其分离为一个类,但是它正在其他2种公共方法中使用,因此我最终将对相同的逻辑进行两次测试。
罗德里戈·鲁伊斯

13

一些很好的答案。我没有看到的一件事是,在测试驱动开发(TDD)中,私有方法是在重构阶段创建的(请参阅Extract Method作为重构模式的示例),因此应该已经具有必要的测试覆盖率。如果做得正确(当然,关于正确性,您将收到很多意见),则不必担心必须公开私有方法以便进行测试。


11

为什么不将堆栈管理算法拆分为实用程序类?实用程序类可以管理堆栈并提供公共访问器。它的单元测试可以集中在实现细节上。对算法上棘手的类进行深入测试对于消除边缘情况并确保覆盖率非常有帮助。

这样,您当前的类就可以干净地委托给实用程序类,而无需暴露任何实现细节。它的测试将与其他人建议的分页要求有关。


10

在Java中,还可以选择将其打包为私有(即不显示可见性修饰符)。如果您的单元测试与被测试的类位于同一程序包中,则它应该能够看到这些方法,并且比完全公开该方法更安全。


10

私有方法通常用作“帮助”方法。因此,它们仅返回基本值,而不会在对象的特定实例上进行操作。

如果要测试它们,则有两种选择。

  • 使用反射
  • 授予方法包访问权限

或者,如果它是新类的足够好的候选者,则可以使用helper方法作为公共方法创建一个新类。

这里有一篇非常好的文章


1
公平的评论。只是一个选择,也许是一个坏选择。
2011年

@Finglas为什么使用反射测试私有代码是一个坏主意?
2014年

@Anshul私有方法是实现细节,而不是行为。换句话说,它们会改变。名称更改。参数更改。内容更改。这意味着这些测试将一直中断。另一方面,就API而言,公共方法要稳定得多,因此更具弹性。提供对公共方法的测试来检查行为而不是实现细节,您应该很好。
Finglas 2014年

1
@Finglas为什么您不想测试实现细节?这是需要工作的代码,并且如果更改频率更高,则您希望它会更频繁地中断,这是比公用API进行更多测试的原因。在您的代码库稳定之后,假设在将来的某个时候有人来了并更改了一个私有方法,这会破坏您的类在内部的工作方式。测试您的班级内部的测试会立即告诉他们,他们损坏了某些东西。是的,这会使维护您的测试变得更加困难,但这是您对全覆盖测试所期望的。
Anshul 2014年

1
@Finglas测试实现细节没有错。那是您的立场,但这是一个广泛争论的话题。测试内部结构会给您带来一些好处,即使可能不需要完全覆盖也是如此。您的测试更加集中,因为您正在直接测试私有方法,而不是通过公共API进行测试,这可能会混淆您的测试。负测试更容易,因为您可以手动使私有成员无效,并确保公共API响应内部状态不一致而返回适当的错误。还有更多示例。
Anshul 2014年

9

如果您使用的是C#,则可以将方法设为内部方法。这样,您就不会污染公共API。

然后将属性添加到dll

[程序集:InternalsVisibleTo(“ MyTestAssembly”)]

现在,所有方法在MyTestAssembly项目中都可见。也许并不完美,但是最好公开私有方法以进行测试。



6

我会说这是一个坏主意,因为我不确定您是否会从中获得任何好处和潜在的问题。如果要更改调用约定,只是为了测试私有方法,就不是在测试类的使用方式,而是创建一个您从未打算发生的虚假方案。

此外,通过将方法声明为公共方法,这意味着在六个月内(忘记了将方法公开的唯一原因是要进行测试之后),您(或者如果您已经将项目移交给了)完全不一样的人赢得了不使用它,可能会导致意想不到的后果和/或进行维护噩梦。


1
如果该类是服务合同的实现,并且只能通过其接口使用,该方法如何-即使私有方法已公开,也不会因为其不可见而被调用
jcvandan

我仍然希望使用公共API(接口)来测试该类,因为否则,如果您重构该类以拆分内部方法,则必须更改测试,这意味着您将不得不花费一些时间。努力确保新测试与旧测试相同。
2011年

同样,如果确保测试覆盖范围包括私有方法中每个边缘情况的唯一方法是直接调用它,则可能表明类复杂性需要重构以简化。
beny23

@dormisher-如果仅通过接口使用该类,则只需测试公共接口方法的行为即可。如果公用方法按照它们的意图进行,那么您为什么还要关心私有方法呢?
安德烈·道尔

@Andrzej-我想我实际上不是应该的,但是在某些情况下,我认为它可能是有效的,例如,用于验证模型状态的私有方法,可能值得测试这样的方法-但是这样的方法应该可以通过以下方式进行测试无论如何,公共接口
jcvandan 2011年

6

在单元测试方面,您绝对不应添加更多方法;我相信您最好针对您的first()方法创建一个测试用例,在每次测试之前都会调用它;那么您可以多次调用- next()previous()last()查看结果是否符合您的期望。我猜如果您不向类中添加更多方法(仅出于测试目的),您将坚持“黑匣子”测试原则;



5

在更新中,您说最好使用公共API进行测试。这里实际上有两所学校。

  1. 黑匣子测试

    黑匣子学校说,该类应被视为一个黑匣子,没人能看到其中的实现。测试此问题的唯一方法是通过公共API-就像该类的用户将使用它一样。

  2. 白盒测试。

    白盒子学校自然而然地认为是利用有关班级实施的知识,然后测试班级以了解其应有的作用。

我真的不能参加讨论。我只是想知道有两种不同的测试类(或库等)的方法会很有趣。


4

实际上,在某些情况下,您应该执行此操作(例如,当您实现一些复杂的算法时)。只需将它设为私有程序包就足够了。但是在大多数情况下,您的类可能太复杂了,需要将逻辑分解为其他类。


4

您想单独测试的私有方法表明您的类中还有另一个“概念”。将“概念”提取到其自己的类中,并作为单独的“单元”对其进行测试。

观看此视频,就该主题进行一次非常有趣的尝试。


4

您永远不要让测试决定您的代码。我并不是说TDD或其他DD,这正是您的要求。您的应用是否需要公开这些方法?如果可以,请对其进行测试。如果没有,则不要将它们公开以进行测试。与变量和其他变量相同。让您的应用程序需求决定代码,让您的测试测试是否满足需求。(再次,我不是要先测试还是要改变类结构以满足测试目标)。

相反,您应该“测试更高”。测试调用私有方法的方法。但是您的测试应该测试您的应用程序需求,而不是您的“实施决策”。

例如(此处为伪伪代码);

   public int books(int a) {
     return add(a, 2);
   }
   private int add(int a, int b) {
     return a+b;
   } 

没有理由测试“添加”,而可以测试“书”。

永远不要让您的测试为您做出代码设计决策。测试您是否获得了预期的结果,而不是如何获得预期的结果。


1
“永远不要让您的测试为您做出代码设计决策”-我必须不同意。难以测试是一种代码味道。如果您无法测试它,怎么知道它没有损坏?
Alfred Armstrong

为了澄清起见,我同意您不应更改例如库的外部API设计。但是您可能需要重构以使其更具可测试性。
Alfred Armstrong,2015年

我发现,如果您需要重构以进行测试,那不是您应该担心的代码味道。您还有其他问题。当然,这是个人经验,我们都可能会以两种方式对可靠数据进行争论。首先,我从来没有遇到过“难以测试”而不是“不良设计”。
coteyr

这种解决方案对于像书籍这样的返回值的方法很有用-您可以在断言中检查返回类型; 但是您将如何检查void方法?
IntelliData

void方法可以执行某些操作,或者它们不需要存在。检查他们所做的事情,
coteyr

2

我倾向于同意,对它进行单元测试的好处大于增加某些成员的可见性的问题。稍有改进是使其受到保护和虚拟化,然后在测试类中对其进行覆盖以使其公开。

或者,如果要单独测试其功能,是否不建议设计中缺少对象?也许您可以将其放在单独的可测试类中……然后您现有的类仅委托给该新类的实例。


2

我通常将测试类与被测类放在同一项目/程序集中。
这样,我只需要internal可见性就可以使函数/类可测试。

这在某种程度上使您的构建过程变得复杂,需要过滤掉测试类。我通过命名所有测试类TestedClassTest并使用正则表达式来过滤这些类来实现此目的。

当然,这仅适用于您问题的C#/ .NET部分


2

我往往会添加一个方法叫做类似validateverifycheck,等,一类,以便它可以被称为测试一个对象的内部状态。

有时,此方法包装在ifdef块中(我主要用C ++编写),因此不会为发布而编译。但是,在发行版中提供验证方法通常很有用,该方法可以使程序的对象树进行检查。


2

番石榴具有@VisibleForTesting批注,用于标记方法的扩展范围(程序包或公共),否则它们会扩展。我对同一件事使用@Private注释。

虽然必须对公共API进行测试,但有时获取通常不公开的内容是方便且明智的。

什么时候:

  • 通过将一个类分解为多个类,可以大大简化一个类的可读性,
  • 只是为了使其更具可测试性
  • 并提供对内脏的一些测试访问将达到目的

宗教似乎胜过工程。


2

我通常将这些方法保留为protected相同的位置,并将单元测试放在相同的程序包中(但在另一个项目或源文件夹中),在这里它们可以访问所有受保护的方法,因为类加载器会将它们放在相同的名称空间中。


2

不可以,因为有更好的方法给那只猫剥皮。

一些单元测试工具依赖于类定义中的宏,这些宏在以测试模式构建时会自动扩展以创建钩子。非常C风格,但可以。

一个简单的OO习惯用法是使您要测试的所有内容都“受保护”,而不是“私有”。测试工具继承自被测类,然后可以访问所有受保护的成员。

或者您选择“朋友”选项。就我个人而言,这是我最不喜欢C ++的功能,因为它破坏了封装规则,但是对于C ++如何实现某些功能,它恰好是必需的,所以。

无论如何,如果您正在进行单元测试,则很有可能需要将值注入这些成员中。白框发短信是完全有效的。这确实破坏您的封装。


2

在.Net中,有一个名为PrivateObjectdeigned 的特殊类,专门允许您访问类的私有方法。

在MSDN上或在Stack Overflow上查看有关此内容更多信息

(我想知道到目前为止没有人提到它。)

在某些情况下,这还不够,在这种情况下,您将不得不使用反射。

我仍然会坚持不要测试私有方法的一般建议,但是像往常一样,总是有例外。


1

正如其他评论所广泛指出的那样,单元测试应重点关注公共API。但是,除了优缺点和理由之外,您还可以使用反射在单元测试中调用私有方法。您当然需要确保您的JRE安全性允许它。调用私有方法是Spring框架与其ReflectionUtils一起使用的(请参见makeAccessible(Method)方法)。

这是一个带有私有实例方法的小型示例类。

public class A {
    private void doSomething() {
        System.out.println("Doing something private.");
    }
}

还有一个执行私有实例方法的示例类。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class B {
    public static final void main(final String[] args) {
        try {
            Method doSomething = A.class.getDeclaredMethod("doSomething");
            A o = new A();
            //o.doSomething(); // Compile-time error!
            doSomething.setAccessible(true); // If this is not done, you get an IllegalAccessException!
            doSomething.invoke(o);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
}

执行B,将打印Doing something private. 如果确实需要,则可以在单元测试中使用反射来访问私有实例方法。


0

就个人而言,在测试私有方法时,我也会遇到相同的问题,这是因为某些测试工具受到限制。如果有限的工具无法响应您的需求,那么您只能靠有限的工具来驱动设计,而不是改变工具而不是设计。因为您要求C#,所以我不能提出好的测试工具,但是对于Java,有两个强大的工具:TestNG和PowerMock,您可以找到适用于.NET平台的相应测试工具。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.