java暴露方法_单元测试(java):我是否必须编写公共方法来将数据暴露给单元测试?...

我已经看过了,但它并没有真正的答案。有时你需要测试一个类的某些行为,但是为了你真正断言你有预期的行为,你需要检查它的一些私有数据。

一个例子:我正在创建一个类,它将返回从文件中读取的随机单词。所以我设计了一个这样的类:

public class WordsDatabase {

private List wordsList = new ArrayList();

public WordsDatabase() {

fillWordsListFromFile();

}

private void fillWordsListFromFile() {...}

public String getRandomWord() {...}

}

我不想暴露wordsList,但是现在如果getRandomWord()真的从我的字典文本文件中获取一个随机单词,我应该如何进行单元测试?

我可以测试的是它是否返回一个单词,但我不知道该单词是否是从文件中随机选取的。

为了测试我可以执行Chi Square测试以进行均匀分布,但是至少我必须知道wordsList.size(),以某种方式暴露它。

也许我只是愿意进行太深入的测试......

编辑:

谢谢你的答案,得到了提示。当我的课很难测试时,可能是因为它的设计有问题。

它并不完全重复,但这个问题非常接近:stackoverflow.com/questions/34571/&

我已经看过了,但是我真的应该为那些思考而烦恼吗?

这属于programmers.stackexchange.com - 用于编程理论/最佳实践的stackexchange站点。 Stack Overflow(本网站)用于特定的编程/代码问题。您的问题是关于单元测试理论/最佳实践/方法。

@mmcrae:这不是偏离主题的。

我会试试看,stackexchange可能有一个"迁移到"功能...

并且在那里提出并回答了一个密切相关的问题:programmers.stackexchange.com/q/199090/25768

不要在这两个网站上发布。选一个。

如果将测试类放在与正在测试的类相同的包(不是相同的源文件夹)中,则可以使用package-private来允许测试类访问,而不会暴露给世界。

谢谢@ratchetfreak,讨论确实有所帮助。

a)事情不需要完全public:stackoverflow.com/a/6913490/995891 b)您的测试可以测试一个小的测试列表,例如: 10件事,调用常规方法1000次并检查你是否大致均匀地得到了所有东西。这当前不起作用,因为您的类无法正确建模它的依赖关系并硬编码它们(也就是使列表可配置)

谢谢@zapl,这真的是我班上的问题。

"如果getRandomWord()真的从我的字典文本文件中获取一个随机单词,我应该如何进行单元测试?"

这听起来像是模拟和依赖注入的完美用例。

更新您的类,以便在构造时传入此字典

在单元测试中,传入内容非常有限的不同模拟字典/将在调用时返回特定数据

在此更新之后,getRandomWord的单元测试只是验证是否使用了模拟wordList中的预期数据。

如果您使用像spring这样的框架,那么它就是为依赖注入而设计的。另一个答案有一些关于使用弹簧来解决这个问题的好指示。

这是一个有趣的解决方案,因此该类不会绑定到单个字典。 实际上这是更好的设计,因为它不是真正的类,而是几乎是一个对象。

将类拆分为两个,一个用于读取,另一个用于从List 获取随机单词不是一个好主意吗?

@LukeW有很多不同的方法来完成重构,以使用依赖注入 - 这是一个可能的想法 - 另一种可能是提取'RandomNumberProvider'作为另一个依赖。 对此的"正确"细分完全取决于周围环境 - 即:这个特定的类如何适应? 还有哪些可以重复使用? 什么可以在别处重复使用? 等等

您应该只测试公共方法,以确定您的类是否按照您的喜好工作。

测试对象的内部状态不是一个好习惯,因为对象的内部表示可以改变,但方法行为可以保持不变。

因此,您无需更改变量/方法的可见性以对单元进行单元测试,并且您不应使用Reflection进行测试(有时它会用作解决此类问题的提示)。

注意:如果你需要知道wordsList的大小。您需要检查wordsList的填充方式。从你的代码看来它是从一个文件填充。因此,您要定义要在测试中使用的文件。知道了这个文件的内容,你不需要检查wordsList大小的内部值。

谢谢,我虽然在测试代码中使用相同的文件,但后来我害怕过度复杂的单元测试,此外我将不得不暴露静态TEXTFILEPATH以确保两者是相同的。

改变您的设计可以让您更轻松地测试您的课程。例如,您可以向WordsDatabase注入一个服务/数据访问对象,该对象实际上是从某些资源中为您检索单词,并且具有mocakable / swappable的优点:

public class WordsDatabase {

private List wordsList = new ArrayList();

public WordsDatabase(WordService wordService) {

wordsList.addAll(wordService.getWords());

}

public String getRandomWord() {

// Interact with wordsList or wordService directly.

}

}

示例服务接口:

public interface WordService {

List getWords();

}

现在,在您的测试中,您可以模拟WordService的实例,该实例返回相应的List字符串,或者提供其他一些受控实现。

如果你控制你的类的依赖性,这种问题(很大程度上)就会消失。查看依赖注入的示例以获取更多信息。

除非你真的没有选择,否则你绝对不应该使用反射进行JUnit测试。如果要执行涉及私有变量的测试,则应使用注入或自动装配。

考虑使用这些类型的注释:

@注入

@Autowire

@豆

@生产

@值

在您的情况下,对于您的列表,@ Inject或@Autowire是最适合注入变量的注释。请记住,您需要定义应用程序上下文。使用Spring或仅使用J2EE或支持CDI的任何其他优秀平台。

更重要的是,如果你出于某种原因拥有私有方法,那么请保持这种方式。我认为通常将方法公开只是为了满足单元测试是一个坏主意。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值