【发布时间】:2018-07-30 04:19:28
【问题描述】:
我有一个像这样的控制器类,它将一些执行程序传递给一个可运行的实例。 这不是它的工作原理,只是为了简单起见,我这样做了。
package com.test.executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Controller {
private ExecutorService executor;
public Controller() {
executor = Executors.newCachedThreadPool();
}
public void doRun() {
MyRunner runner = new MyRunner(executor);
Thread myRunner = new Thread(runner);
myRunner.start();
}
public static void main(String[] args) {
new Controller().doRun();
}
}
运行器接收执行器的实例,然后传递某些可调用对象。 现在,callables 有点多样化,因为一些 callables 访问数据库/调用一些 web 服务/文件系统
我在如何为这种情况下编写合适的 JUnit 时遇到了一些问题。 我希望有尽可能多的代码覆盖率。
package com.test.executor;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class MyRunner implements Runnable {
private ExecutorService executor;
public MyRunner(ExecutorService executor) {
this.executor = executor;
}
@Override
public void run() {
// TODO Auto-generated method stub
Future<Boolean> ret1 = executor.submit(new SampleCall1());
try {
ret1.get(5, TimeUnit.MINUTES);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
// Do other things
Future<List<String>> ret2 = executor.submit(new SampleCall2());
try {
ret2.get(5, TimeUnit.MINUTES);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
// Do other things
Future<Long> ret3 = executor.submit(new SampleCall3());
try {
ret3.get(5, TimeUnit.MINUTES);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
}
public static class SampleCall1 implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
// Sample Return Only
// This will call JSON web service
return true;
}
}
public static class SampleCall2 implements Callable<List<String>> {
@Override
public List<String> call() throws Exception {
// Sample Return Only
// This will call Database
return Collections.EMPTY_LIST;
}
}
public static class SampleCall3 implements Callable<Long> {
@Override
public Long call() throws Exception {
// Sample Return Only
// This will access some file system
return 1L;
}
}
}
我的问题是为此编写单元测试的正确方法是什么。我正在收集一些关于如何对这个类进行单元测试的建议? 我不确定在我的 junit/mockito 实例中要模拟什么。 我应该模拟每个可调用对象吗?然后为 MyRunner 创建一个测试用例。
我担心依赖性..因为我正在连接到数据库/Web 服务/和文件系统,所以我想寻求一些建议。
更新 2
package com.test.executor;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class MyRunner implements Runnable {
private ExecutorService executor;
public MyRunner(ExecutorService executor) {
this.executor = executor;
}
@Override
public void run() {
executeTasks1();
// Do other things
executeTasks2();
// Do other things
executeTasks3();
}
public boolean executeTasks1(){
// TODO Auto-generated method stub
Future<Boolean> ret1 = executor.submit(new SampleCall1());
try {
return ret1.get(5, TimeUnit.MINUTES);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
}
public List<String> executeTasks2(){
Future<List<String>> ret2 = executor.submit(new SampleCall2());
try {
return ret2.get(5, TimeUnit.MINUTES);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
}
public Long executeTasks3(){
Future<Long> ret3 = executor.submit(new SampleCall3());
try {
return ret3.get(5, TimeUnit.MINUTES);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
}
public static class SampleCall1 implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
// Sample Return Only
// This will call JSON web service
return true;
}
}
public static class SampleCall2 implements Callable<List<String>> {
@Override
public List<String> call() throws Exception {
// Sample Return Only
// This will call Database
return Collections.EMPTY_LIST;
}
}
public static class SampleCall3 implements Callable<Long> {
@Override
public Long call() throws Exception {
// Sample Return Only
// This will access some file system
return 1L;
}
}
}
【问题讨论】:
-
只需单独对 Callables 进行单元测试,并用适当的“答案”模拟执行器来测试“MyRunner”的逻辑。
-
我不明白你的问题:可调用和执行器的整个概念是将可调用的智能与执行调度逻辑分开。现在,当 unit 测试时,您只需要测试您对接口的期望。 TL;DR 单元独立测试可调用对象,UT 你的控制器,不要 UT 执行器,因为那是 Spring 代码,不要编写混合所有内容的测试,这不是单一的。
标签: java unit-testing junit mockito