带输入的方法上的Java单元测试

时间:2018-10-09 13:51:05

标签: java unit-testing

当我使用方法“ execute(p)”时,必须选择一个项目时会有一个列表:

@Override
public void execute(Player p) {
    // listchoser with items available
    ListChoser lc = new ListChoser();
    Object itemChosen;
    itemChosen = lc.chose("Which item?", p.getCurrentRoom().getItems());
    System.out.println("You chose " + itemChosen.toString());
    // put item effect on player
    ((Item) itemChosen).effect(p);
    // remove item from current room
    p.getCurrentRoom().removeItem(itemChosen);
}

我必须对此进行一些单元测试,以便在这里进行操作:

Player c;
Action useAction;

@Before
public void initiliaze() {
    c = new Player("Test", 100, 100,100);
    c.setCurrentRoom(new Room("Debug Room", false));
    useAction = new UseAction();
}

@Test
public void testUseAction(){
    List<? super Item> l = c.getCurrentRoom().getItems();
    int nbItems = l.size();
    useAction.execute(c);
    assertEquals(nbItems-1, c.getCurrentRoom().getItems().size());
}

启动此类测试时,我遇到了一些麻烦:当我仅应使用默认值(如0)时,要求输入

2 个答案:

答案 0 :(得分:1)

我建议将execute()方法拆分为2个单独的方法,因此它们中的第一个仅接收输入,对其进行处理,并将操作结果传递给包含所有其他逻辑的第二个。

这使您的代码符合SOLID的“单一职责”原则,并且还可以测试代码中负责逻辑的那部分,而无需用户提供任何输入(您可以传递一些准备好的对象)< / p>

答案 1 :(得分:1)

交互式代码和单元测试不匹配。这就是为什么“测试优先”方法有助于编写干净且可测试的代码的原因。如果事后编写测试代码,则出于可测试性,您不得不花时间重写程序代码。

一种快速而肮脏的解决方案是添加另一个方法,并从现有方法中调用它,如下所示:

@Override
public void execute(Player p) {
    execute(Player p, new ListChoser());
}

public void execute(Player p, ListChoser lc) {
    Object itemChosen;
    if (lc != null) {
        itemChosen = lc.chose("Which item?", p.getCurrentRoom().getItems());
        System.out.println("You chose " + itemChosen.toString());
    }
    else { //add exception handling if list is empty
        itemChosen = p.getCurrentRoom().getItems()[0];
    }
    // put item effect on player
    ((Item) itemChosen).effect(p);
    // remove item from current room
    p.getCurrentRoom().removeItem(itemChosen);
}

并使用这种新方法进行测试,例如:

@Test
public void testUseAction(){
    List<? super Item> l = c.getCurrentRoom().getItems();
    int nbItems = l.size();
    useAction.execute(c, null); //use null for default behaviour
    assertEquals(nbItems-1, c.getCurrentRoom().getItems().size());
} 

这样,您至少可以测试代码的非交互部分。

更好的解决方案是完全重新设计ListChoser作为接口并实现InteractiveListChoserTestListChoser。将类型(=接口)与实现(= class)分开是一种设计原理,非常适合单元测试。