如何对有两个公共方法的情况进行单元测试,一个调用另一个?

时间:2017-04-06 11:29:42

标签: java unit-testing junit mockito

当有两个公共方法并且一个方法在同一个类中调用另一个公共方法时,测试方法的方法是什么?

在这种情况下我应该如何编写单元测试?

一个例子

const int BITS_PER_BYTE = 8; // amount of bits per one byte

int elementBitsSize = sizeof(short) * BITS_PER_BYTE; // size in bits of one element in array
bool[] bBuf = new bool[sBuf.Length * elementBitsSize]; // new array size

// iterate through each short value
for ( int i = 0; i < sBuf.Length; ++i )
{
    // iterate through bits in that value
    for( int j = 0; j < elementBitsSize; ++j )
    {
        // assign new value
        bBuf[j + i * elementBitsSize] = Convert.ToBoolean(sBuf[i] & (1 << j));
    }
}

这个例子并没有显示所涉及的方法的复杂性,而是概念。

我应该分别测试class SpecificIntMath { public int add(int a,int b) { return a+b; } public int multiply(int a, int b) { int mul = 0; for(int i = 0;i<b,i++) { mul=add(a,mul); } return mul; } } add吗?如果我只测试multiply,我觉得我们错过了multiply无法提供参数的情况。

假设要单独测试multiplemultiply,我是否可以模拟add?怎么可能?

假设addmultiply需要单独测试而且我不应该模拟,我应该让add按原样运行。如果是这种情况,我应该如何处理add内的程序流程?

测试这种情况的方法是什么。

编辑1:

在下面的代码中,

add

我应该在测试class MCVC { public boolean getWhereFrom(List<User> users) { boolean allDone = true; for(User user: users){ String url = user.getUrl(); switch(url) { case Consts.GOOGLE: someDao.updateFromAddr(user); user.setEntry("Search Engine"); break; case Consts.FACEBOOK: someDao.updateFromAddr(user); user.setEntry("Social Media"); break; case Consts.HOME: someDao.updateToAddr(user); user.setEntry("Company"); default user.setEntry(null); allDone = false; break; } } return allDone; } public void likedDeck() { List<Users> usersList = deckDao.getPotentialUsers(345L,HttpStatus.OK); boolean flag = getWhereFrom(usersList); if(flag) { for(User user: usersList) { //some Action } } } } 时考虑getWhereFrom()还是应该假设任何默认情况?如果我考虑默认情况,我会输出输出不是默认值的情况。我不确定我是否应该嘲笑它,因为调用的类正在测试中。 Spying/Mocking class under test

3 个答案:

答案 0 :(得分:2)

你不在乎。

您可以使用单元测试来自行测试每个公共方法的合同。因此,您编写测试以确保add()multiply()执行他们应该执行的操作。

内部使用另一个的事实对外界没有兴趣。您的测试既不应该知道也不关心这个内部实现细节。

仅供记录:因为您的代码现在正在编写;你绝对不要在这里转向嘲笑。这里不需要嘲笑;只有添加测试一些 nothing 与您的真实生产代码有关的东西的风险。当您必须控制对象的各个方面以启用测试时,使用模拟。但是,您的示例代码中没有任何内容需要进行模拟测试。如果它会 - 它将表明设计/实施不佳(鉴于这些方法的合同)!

编辑;给出问题中的变化示例:

首先,getWhereFrom()中存在错误 - 您迭代列表;但是你会继续覆盖该列表中的返回值。所以当第一次迭代将结果设置为false时;该信息可能会在下一个循环中丢失。

我看到了实际问题的两个选项:

  • 你转向Mockito;和它的间谍&#34;做部分嘲笑的概念;如果您想保持源代码不变,
  • 我个人;我宁愿花时间改进生产代码。我认为getWhereFrom()可能值得拥有类(我可能不会在列表的用户身上使用它;但只是一个用户;这也有助于返回一个布尔值;-)。当你这样做时,你可以使用依赖注入来获取一个(模拟的)实例&#34; WhereFromService&#34;类。

换句话说:您展示的代码可以重新加工/重构;例如,更清楚地遵循SRP。但这当然是一项更大的事业;你需要与周围的人讨论。

答案 1 :(得分:0)

至少要分别测试它们。乘法测试隐式测试添加是没有问题的。在大多数情况下,你应该问自己这两个方法是否有必要公开的问题。

答案 2 :(得分:0)

  

我应该单独测试加法和乘法吗?

如果您正在进行单元测试,则应单独测试它们。您只想在进行组件或集成测试时一起测试它们。

  

假设乘法和加法单独测试,我应该能够   模拟添加?

  

这怎么可能?

使用mockito或任何其他模拟框架。具体如何在这里看到Use Mockito to mock some methods but not others

  

假设乘法和加法单独测试,我不应该   mock,我应该按原样添加执行。

我不会这样做。 add中的内部更改可能会影响多次测试,您的测试会变得更加复杂和不稳定。