单元测试私有字段
Unit testing private fields
我有一个简单的 class,其中包含一个列表:
public class SomeClass {
private AppDataSource appDataSource; // it's interface
private List<Object> someList;
////
public List<Obejct> loadSomeList() {
if (someList == null) {
return appDataSource.getListFromDatabase();
}
retrunf someList;
}
}
重点是——我希望该列表只从数据库加载一次。我想对这个功能进行单元测试。我是 TDD 的菜鸟,我所能做的就是为 someList 写一个 public getter 和 setter 并在单元测试中使用它们。但它在概念上是错误的——我不希望 class 的客户直接使用这个成员变量。
在这种情况下如何正确测试方法?
您可以通过测试夹具中的构造函数初始化您的私有字段。我猜这是最常见的方式。
另一种选择是在Groovy中编写测试,可以直接访问Java类中的私有字段。因此,您无需授予对私有字段的访问权限。
您可以像这样测试您的 loadSomeList()
:
public class SomeClass {
private List<Object> someList;
public List<Object> loadSomeList() {
if (someList == null) {
someList = new ArrayList<>();
someList.add(new Object());
return someList;
}
return someList;
}
public List<Object> getSomeList() {
return someList;
}
public void setSomeList(List<Object> someList) {
this.someList = someList;
}
测试 Class 应该有两个测试:
- 在第一个测试中,您可以测试是否有新列表。你创造一个
SomeClass 的新实例并调用你的
someClass.loadSomeList()
方法。如果列表不为空,则测试正常。
- 第二个测试你可以测试你的
someClass
实例是否已经有一个列表。在测试中,您只需在列表中添加一个对象并将其设置为 someClass
.
public class SomeClassTest {
@Test
public void testLoadSomeListNewList() {
SomeClass someClass = new SomeClass();
List<Object> list = someClass.loadSomeList();
assertNotNull(list);
}
@Test
public void testLoadSomeListGivenList() {
SomeClass someClass = new SomeClass();
List<Object> list = new ArrayList<>();
list.add(new Object());
someClass.setSomeList(list);
someClass.loadSomeList();
assertTrue(someClass.getSomeList().size() == 1);
}
如果您在测试目录中创建一个与您的包同名的包class,并且如果您将该字段置于受保护状态,您将能够直接访问该字段
您应该在测试 coming.Use @Before 之前模拟您的列表以初始化您的列表。
private List<Object> someList;
@Before
public void initialize() {
someList = new ArrayList<Object>();
someLisi.add(..);
someList.add(..);
}
并使用此模拟测试您的方法 list.You 也可以使用 @BeforeClass for mocking your list. You can read differences between @Before and @BeforeClass here
您的单元测试有误。
单元测试是关于测试您的 class 的 行为 ;不是实施细节。
您不测试私有字段是否有这个或那个内容。您测试的唯一一件事是方法执行它们应该执行的操作。
那当然意味着你的class必须有办法插入"special lists"进行测试。
长话短说:你想退一步,又度过了接下来的2、3个小时
学习如何写作 "easy to test code";例如,观看来自 Google Tech on CleanCode 的精彩视频。
与其公开和测试列表,不如更改您的 appDataSource,以便您可以从 class 外部设置它。使其成为提供 getListFromDatabase() 方法的接口。然后为了测试,传入一个实现接口的模拟数据源,并有一个计数器,您可以查询该计数器以告诉您 getListFromDatabase 方法被调用了多少次。
看看你想测试什么,然后朝着那个方向努力。你没有在你的标准中提到列表本身很重要。重要的是您查询数据库的次数。
我有一个简单的 class,其中包含一个列表:
public class SomeClass {
private AppDataSource appDataSource; // it's interface
private List<Object> someList;
////
public List<Obejct> loadSomeList() {
if (someList == null) {
return appDataSource.getListFromDatabase();
}
retrunf someList;
}
}
重点是——我希望该列表只从数据库加载一次。我想对这个功能进行单元测试。我是 TDD 的菜鸟,我所能做的就是为 someList 写一个 public getter 和 setter 并在单元测试中使用它们。但它在概念上是错误的——我不希望 class 的客户直接使用这个成员变量。
在这种情况下如何正确测试方法?
您可以通过测试夹具中的构造函数初始化您的私有字段。我猜这是最常见的方式。
另一种选择是在Groovy中编写测试,可以直接访问Java类中的私有字段。因此,您无需授予对私有字段的访问权限。
您可以像这样测试您的 loadSomeList()
:
public class SomeClass {
private List<Object> someList;
public List<Object> loadSomeList() {
if (someList == null) {
someList = new ArrayList<>();
someList.add(new Object());
return someList;
}
return someList;
}
public List<Object> getSomeList() {
return someList;
}
public void setSomeList(List<Object> someList) {
this.someList = someList;
}
测试 Class 应该有两个测试:
- 在第一个测试中,您可以测试是否有新列表。你创造一个
SomeClass 的新实例并调用你的
someClass.loadSomeList()
方法。如果列表不为空,则测试正常。 - 第二个测试你可以测试你的
someClass
实例是否已经有一个列表。在测试中,您只需在列表中添加一个对象并将其设置为someClass
.
public class SomeClassTest {
@Test
public void testLoadSomeListNewList() {
SomeClass someClass = new SomeClass();
List<Object> list = someClass.loadSomeList();
assertNotNull(list);
}
@Test
public void testLoadSomeListGivenList() {
SomeClass someClass = new SomeClass();
List<Object> list = new ArrayList<>();
list.add(new Object());
someClass.setSomeList(list);
someClass.loadSomeList();
assertTrue(someClass.getSomeList().size() == 1);
}
如果您在测试目录中创建一个与您的包同名的包class,并且如果您将该字段置于受保护状态,您将能够直接访问该字段
您应该在测试 coming.Use @Before 之前模拟您的列表以初始化您的列表。
private List<Object> someList;
@Before
public void initialize() {
someList = new ArrayList<Object>();
someLisi.add(..);
someList.add(..);
}
并使用此模拟测试您的方法 list.You 也可以使用 @BeforeClass for mocking your list. You can read differences between @Before and @BeforeClass here
您的单元测试有误。
单元测试是关于测试您的 class 的 行为 ;不是实施细节。
您不测试私有字段是否有这个或那个内容。您测试的唯一一件事是方法执行它们应该执行的操作。
那当然意味着你的class必须有办法插入"special lists"进行测试。
长话短说:你想退一步,又度过了接下来的2、3个小时 学习如何写作 "easy to test code";例如,观看来自 Google Tech on CleanCode 的精彩视频。
与其公开和测试列表,不如更改您的 appDataSource,以便您可以从 class 外部设置它。使其成为提供 getListFromDatabase() 方法的接口。然后为了测试,传入一个实现接口的模拟数据源,并有一个计数器,您可以查询该计数器以告诉您 getListFromDatabase 方法被调用了多少次。
看看你想测试什么,然后朝着那个方向努力。你没有在你的标准中提到列表本身很重要。重要的是您查询数据库的次数。