当我使用方法“ 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)时,要求输入
答案 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
作为接口并实现InteractiveListChoser
和TestListChoser
。将类型(=接口)与实现(= class)分开是一种设计原理,非常适合单元测试。