设计先行,测试迭代
需求 设计先行
设计一个task模块
- [添加一个 Task 项]
task add <item>
1. <item>
Item <itemIndex> added
- [完成一个 Task 项]
task done <itemIndex>
Item <itemIndex> done.
- [Task 项列表] 列出指定task
task list 1. <item1> 2. <item2>
Total: 2 items
列出所有task
task list --all
1. <item1>
2. <item2>
3. [Done] <item3>
Total: 3 items, 1 item done
领域服务设计
识别名词 -> TASK项服务
- [addTodoItem,添加 Task 项]
- [markTodoItemDone,完成一个 Task 项]
- [list,列出所有的 Task 项]
Repository -> TASK项的持久化
任务分解
- [ ADD接口 ]
TaskItem addTaskItem(final TaskItem item);
设计规范
1.对于输入参数的检测,由入口部分代码进行处理。
2.Repository 的问题以运行时异常的形式抛出,业务层不需要做任何处理。
测试场景
添加正常的参数对象,返回一个创建好的 Todo 项;
添加空的参数对象,抛出异常。
测试用例
@Test
public void should_add_task_item() {
TaskRepository repository = mock(TaskRepository.class);
when(repository.save(any())).then(returnsFirstArg());
ITaskService service = new TaskService(repository);
Task item = service.addTaskItem(new Task(0, "task1"));
assertThat(item.getName()).isEqualTo("task1");
}
@Test
public void should_throw_exception_for_null_task_item() {
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> service.addTaskItem(null));
}
接口实现
public TaskItem addTaskItem(TaskItem item) {
if (item == null) {
throw new IllegalArgumentException("null or empty parameters is not allowed!");
}
return taskRepository.save(item);
}
- [ MarkTaskDone接口 ]
Optional<TodoItem> markTaskItemDone(Task task);
测试场景
对于一个已经存在的 Todo 项,将其标记已完成;
如果索引超出现有的索引范围,则返回空。
测试用例
@BeforeEach
public void setUp() {
this.repository = mock(TaskRepository.class);
this.service = new TaskService(this.repository);
}
@Test
public void should_mark_task_item_as_done() {
Task task = new Task(0, "task1");
when(repository.findAll()).thenReturn(ImmutableList.of(new Task(0, "task1"))
when(repository.save(any())).then(returnsFirstArg());
final Optional<TodoItem> taskItem = service.markTaskItemDone(task);
assertThat(taskItem).isPresent();
final Task actual = taskItem.get();
assertThat(actual.getStatus()).isTrue();
}
接口实现
public Optional<TodoItem> markTaskItemDone(TaskItem item) {
if (item == null) {
throw new IllegalArgumentException("null or empty parameters is not allowed!");
}
Optional<Task> optionalTask = repository.findById(item.getId());
if (optionalTask.isPresent()) {
item.setDone(true);
repository.save(item);
}
return optionalTask;
}
- [ List接口 ]
List<Task> list(final boolean all);
设计规范
all 参数为 true 时,列出所有的 Task 项;
false 的时候,列出未完成的 Task 项。
测试场景
如果有 Task 项,罗列 Task 项时,列出所有的 Task 项;
如果没有 Task 项,罗列 Task 项时,列出 Task 项为空;
如果有未完成的 Task 项,罗列未完成 Task 项,列出所有未完成的 Task 项;
如果没有未完成的 Task 项,罗列未完成 Task 项,列出的 Task 项为空。
测试用例
@BeforeEach
public void setUp() {
this.repository = mock(TaskRepository.class);
this.service = new TaskService(this.repository);
}
@Test
public void list_all() {
Task task = new Task(0, "task1");
when(repository.findAll()).thenReturn(ImmutableList.of(new Task(0, "task1"))
List<Task> list = service.list(true);
assertThat(list.size() == 1).isTrue();
}
@Test
public void list_all_empty() {
Task task = new Task(0, "task1");
when(repository.findAll()).thenReturn(new ArrayList())
List<Task> list = service.list(true);
assertThat(list.size() == 0).isTrue();
}
list_false 如上
接口实现
public List<Task> list(final boolean all) {
List<Task> tasks = repository.findAll();
if(all) {
return tasks;
}else{
return repository.findAll().stream().filter(item -> item.getStatus().equals(true)).collect(Collectors.toList());
}
}