繁体   English   中英

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

[英]Java Unit Test on method with input

当我使用方法“ 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)时,要求输入

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

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

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

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

@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)分开是一种设计原理,非常适合单元测试。

暂无
暂无

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

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