在Java中保持单元测试的隔离
我刚刚开始学习Java,我对如何在保持一切隔离的同时对Java类进行单元测试感到困惑。具体来说,我想知道如何在本例中测试像在Java中保持单元测试的隔离,java,unit-testing,Java,Unit Testing,我刚刚开始学习Java,我对如何在保持一切隔离的同时对Java类进行单元测试感到困惑。具体来说,我想知道如何在本例中测试像createProgram这样的方法: package com.example.app; import javax.jdo.JDOHelper; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; import com.example.data_models.Pr
createProgram
这样的方法:
package com.example.app;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import com.example.data_models.Program;
public class ProgramCreator {
private PersistenceManagerFactory pm_factory;
public ProgramCreator(PersistenceManagerFactory pm_factory) {
this.pm_factory = pm_factory;
}
public void createProgram(String name, String instructor, double price) {
PersistenceManager pm = getPersistenceManager();
try {
pm.makePersistent(new Program(name, instructor, price));
} finally {
pm.close();
}
}
private PersistenceManager getPersistenceManager()
{
return this.pm_factory.getPersistenceManager();
}
}
我很确定我可以使用像
mockito
这样的库模拟持久性管理器工厂,并使用它来测试makePersistent
方法是否使用正确的参数调用,但是我如何检查程序数据模型的字段是否正确,同时仍然保持所有内容的隔离?我不想依赖程序对象的getter方法,因为这会导致我对ProgramCreator
的单元测试依赖于program
类是否正确。在这种情况下我该怎么办?(使用Ruby时,我可能只会删除程序
类的新方法。在Java中可能会出现类似的情况吗?中的一个单元不一定局限于单个类,它是一起工作的最小类集。因此,在测试ProgramCreator
时使用Program
的getter没有什么错,您不必到处测试所有内容
照你说的做:模拟适当的代码来测试createProgram
,看看结果是否与你期望的一样(aka:有一个程序使用给定的字段持久化)
您不必测试您是否实际创建了一个包含这些字段的新程序。您也可以使用不同的方法测试新程序(名称、讲师、价格)
是否创建了具有正确值的新对象
单元测试最重要的部分是以下流程:
->总体思路
->执行的逻辑
->结束局势
你的情况填补了这个空缺
->我想用变量X、Y和Z测试createProgram
->??
->数据库应该返回一个值为X、Y和Z的程序
总之,只要最终结果有效,你并不在乎第二步会发生什么。出于这个原因,您可以在代码中允许更多基本上执行逻辑的通用测试,并检查所有这些测试的结果是否与您期望的输出一致
当然,最明显的问题是:如果出现错误,这是否意味着我必须手动调试才能找到问题?是的。这就是为什么您应该添加许多较小的测试(比如测试构造函数)来帮助确定确切的问题
使用getter和setter肯定没有错。事实上,你肯定需要它们。它是关于测试工作流的,不一定要测试孤立的方法。通过在createProgram方法中创建对象(程序),您正在创建对象之间的紧密耦合。相反,将创建工作委托给工厂,您可以在单元测试中模拟工厂。这意味着我们将只测试createProgram方法正在做的事情,而不测试其他事情。尝试对代码进行单元测试可以为我们提供重新设计/重新考虑代码的指示
public class ProgramCreator {
private PersistenceManagerFactory pm_factory;
private ProgramFactory p_factory;
public ProgramCreator(PersistenceManagerFactory pm_factory, ProgramFactory pFactory) {
this.pm_factory = pm_factory;
this.p_factory = pFactory;
}
public void createProgram(String name, String instructor, double price) {
PersistenceManager pm = getPersistenceManager();
try {
pm.makePersistent(p_Factory.createProgram(name, instructor, price));
} finally {
pm.close();
}
}
}
但是这不是一个集成测试而不是一个单元测试吗?这并不是我想避免使用getter和setter,而是我想避免测试被测对象以外的任何东西。这肯定更像是一个集成测试,但是对于一个只将一个操作委托给另一个类中的方法的方法,你会确切地测试什么呢?您可以安全地假设,使用几个参数调用方法将按预期工作:将使用这些参数调用该方法。如果您想对这些参数执行逻辑,那么您使用的测试方法是错误的;这种方法没有太多的逻辑。我仍然有点好奇,是否可以在不依赖它创建的类的正确性(Program
)的情况下测试这样的方法。但是我的对象不会耦合到工厂吗?我也需要在这里使用依赖注入吗?@Ajedi32是的,程序工厂的依赖注入应该是解决这个问题的方法。我已经编辑了上面的回复,以澄清问题。嗯,好吧,听起来很合理。