简体   繁体   English

使用noparameters分支的void方法的测试用例

[英]Test case for void method with noparameters branches

I have String method with no arguments, but it having if conditions. 我有没有参数的String方法,但它有if条件。

public String id1()
{
    Random random=new Random();
    int i=random.nextInt();
    if(i<0)
    {
        i=-(i);
    }
    if(i<1000)
        i=i+1000;
    while(i>9999)
    {
        i=i/10;
    }
    return i+"";
}

How can I write aa Junit test case in this situation? 在这种情况下如何编写一个Junit测试用例?

You could break the logic into its own method: 您可以将逻辑分解为自己的方法:

public String id1(int i)
{
    if(i<0)
    {
        i=-(i);
    }
    if(i<1000)
        i=i+1000;
    while(i>9999)
    {
        i=i/10;
    }
    return i+"";
}

Then change the way you call id1 by just passing it a random int: 然后通过传递一个随机int来改变你调用id1的方式:

id1(new Random().nextInt());

Then you can test the logic. 然后你可以测试逻辑。 This is the easiest, if not the most perfect, solution. 这是最简单的解决方案,即使不是最完美的解决方案。 The more difficult solution is to mock the nextInt() method so you control what it returns inside your test - probably not necessary here, but for some situations that will be the only way. 更难的解决方案是模拟nextInt()方法,以便控制它在测试中返回的内容 - 这里可能没有必要,但对于某些情况来说是唯一的方法。

Something like this. 像这样的东西。 Your test class: 你的考试班:

import java.util.Random;

public class Simple {
    public String id1()
    {
        Random random=new Random();
        int i=random.nextInt();
        if(i<0)
        {
            i=-(i);
        }
        if(i<1000)
            i=i+1000;
        while(i>9999)
        {
            i=i/10;
        }
        return i+"";
    }
}

Tests(I use powermock-mockito-1.6.2). 测试(我使用powermock-mockito-1.6.2)。 You should manipulate generated number: 你应该操纵生成的数字:

import java.util.Random;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Random.class, Simple.class })
public class SimpleTest {

    @Test
    public void ifGenerateNumberLessZeroSetItMoreThanZero() throws Exception {
        Random rand = Mockito.mock(Random.class);
        PowerMockito.mockStatic(Random.class);
        PowerMockito.whenNew(Random.class).withNoArguments().thenReturn(rand);

        Mockito.when(rand.nextInt()).thenReturn(-9999);

        Simple simple = new Simple();
        Assert.assertEquals("9999", simple.id1());
    }
}

Your problem is that you created untestable code. 您的问题是您创建了不可测试的代码。

The point is: if a method creates the input it is working on itself ... then there is simply no testing that method. 关键是:如果一个方法创建输入它正在自行工作......那么根本没有测试该方法。 Yes, you could use PowerMock to gain control over the random class, but that is the completely wrong approach. 是的,您可以使用PowerMock来控制随机类,但这是完全错误的方法。 PowerMock is simply something that nobody should be using (see here for some reasons behind that); PowerMock简直就是没人应该使用的东西(见这里有一些原因); if at all, you use it for 3rd party code that you can't change. 如果有的话,你将它用于你无法改变的第三方代码。 But when we are talking about your own code, then it is much better to come up with testable designs; 但是当我们谈论你自己的代码时,那么提出可测试的设计要好得多; instead of creating a bad design, to then turn to PowerMock to somehow test it. 而不是创建一个糟糕的设计,然后转向PowerMock以某种方式测试它。

In general, you use dependency injection in order to gain control over the "data" that your methods will be working with; 通常,您使用依赖注入来控制您的方法将使用的“数据”; in this case, that could be as simple as: 在这种情况下,这可能很简单:

public String formatStringIdFrom(int id) { ... }

If you really want to improve the quality of your code, I recommend you to step back for some 3, 5 hours and watch all the videos from this google tech series ... believe me, it is absolutely worth your time. 如果你真的想提高你的代码质量,我建议你退后三五个小时,观看这个谷歌科技系列的所有视频......相信我,这绝对值得你花时间。

Some other notes: 其他一些说明:

  • The essence of good unit tests are ... they always return the same result. 好的单元测试的本质是......它们总是返回相同的结果。 This means: code that is based on random values ... should at least allow for providing a seed so that you can write test cases that are guaranteed to always see the same input. 这意味着:基于随机值的代码......至少应该允许提供种子,以便您可以编写保证始终看到相同输入的测试用例。 Unit tests that give you different results in each run ... are simply: not very helpful. 在每次运行中给出不同结果的单元测试......简单地说:不是很有用。
  • id1() is a pretty useless name for a method. id1()是一个非常无用的名称。 It doesn't tell you anything about what method is supposed to do 它不会告诉你应该怎么做什么方法
  • Consider creating a concrete class that really represents IDs. 考虑创建一个真正代表ID的具体类。 Good design is about creating abstractions that allow you to deal with things in a more meaningful way. 好的设计是关于创建抽象 ,让你以更有意义的方式处理事情。 Just pushing around integers; 只是推动整数; and declaring that any 4-digit string made from such an integer is an "id" ... is simply a very naive approach. 并声明由这样的整数构成的任何4位数字符串都是“id”......这只是一种非常天真的方法。
  • Finally: you can dramatically simplify the generation of 4 digit numbers; 最后:您可以大大简化4位数的生成; you only need: int number = random.nextInt(9000) + 1000 directly gives you values between (1000, 9999). 你只需要: int number = random.nextInt(9000) + 1000直接给你int number = random.nextInt(9000) + 1000之间的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM