如何为具有局部变量的方法编写 Junit 测试
How to write Junit test for methods with local variables
我写了一个方法,要求用户按回车键继续,一段时间后超时。
我在使用 Mockito 为这种方法编写 Junit 测试时遇到困难。下面是方法。
private static final ExecutorService l = Executors.newFixedThreadPool(1);
private static String getUserInputWithTimeout(int timeout) {
Callable<String> k = () -> new Scanner(System.in).nextLine();
LocalDateTime start = LocalDateTime.now();
Future<String> g = l.submit(k);
while (ChronoUnit.SECONDS.between(start, LocalDateTime.now()) < timeout) {
if (g.isDone()) {
try {
String choice = g.get();
return choice;
} catch (InterruptedException | ExecutionException | IllegalArgumentException e) {
logger.error("ERROR", e);
g = l.submit(k);
}
}
}
logger.info("Timeout...");
g.cancel(true);
return null;
}
我尝试模拟 Callable 和 Future,但由于此方法是在本地创建它们,因此在 Test 中创建它们没有任何影响。
我尝试了一些方法,但没有按预期工作,我可能做错了。
@Test
public void testgetUserInputWithUserInput() throws Exception {
Scanner scanner = new Scanner(System.in);
Callable<String> callable = PowerMockito.mock(Callable.class);
ExecutorService executorServiceMock = PowerMockito.mock(ExecutorService.class);
Future<String> futureMock = PowerMockito.mock(Future.class);
when(executorServiceMock.submit(any(Callable.class))).thenReturn(futureMock);
assertEquals("", getUserInputWithTimeout(3));
}
我会说你需要稍微改变你的方法,将可调用对象从方法中取出并将其作为参数传递,这应该可以解决你的模拟问题。
private static final ExecutorService l = Executors.newFixedThreadPool(1);
private static String getUserInputWithTimeout(int timeout, Callable<String> k) {
LocalDateTime start = LocalDateTime.now();
Future<String> g = l.submit(k);
while (ChronoUnit.SECONDS.between(start, LocalDateTime.now()) < timeout) {
if (g.isDone()) {
try {
String choice = g.get();
return choice;
} catch (InterruptedException | ExecutionException | IllegalArgumentException e) {
logger.error("ERROR", e);
g = l.submit(k);
}
}
}
logger.info("Timeout...");
g.cancel(true);
return null;
}
您的测试应如下所示:
@Test
public void testgetUserInputWithUserInput() throws Exception {
String ENTER = " ";
System.setIn(new ByteArrayInputStream(ENTER.getBytes()));
Callable<String> callable = () -> new Scanner(System.in).nextLine();
assertEquals(ENTER, getUserInputWithTimeout(5, callable));
}
我写了一个方法,要求用户按回车键继续,一段时间后超时。 我在使用 Mockito 为这种方法编写 Junit 测试时遇到困难。下面是方法。
private static final ExecutorService l = Executors.newFixedThreadPool(1);
private static String getUserInputWithTimeout(int timeout) {
Callable<String> k = () -> new Scanner(System.in).nextLine();
LocalDateTime start = LocalDateTime.now();
Future<String> g = l.submit(k);
while (ChronoUnit.SECONDS.between(start, LocalDateTime.now()) < timeout) {
if (g.isDone()) {
try {
String choice = g.get();
return choice;
} catch (InterruptedException | ExecutionException | IllegalArgumentException e) {
logger.error("ERROR", e);
g = l.submit(k);
}
}
}
logger.info("Timeout...");
g.cancel(true);
return null;
}
我尝试模拟 Callable 和 Future,但由于此方法是在本地创建它们,因此在 Test 中创建它们没有任何影响。
我尝试了一些方法,但没有按预期工作,我可能做错了。
@Test
public void testgetUserInputWithUserInput() throws Exception {
Scanner scanner = new Scanner(System.in);
Callable<String> callable = PowerMockito.mock(Callable.class);
ExecutorService executorServiceMock = PowerMockito.mock(ExecutorService.class);
Future<String> futureMock = PowerMockito.mock(Future.class);
when(executorServiceMock.submit(any(Callable.class))).thenReturn(futureMock);
assertEquals("", getUserInputWithTimeout(3));
}
我会说你需要稍微改变你的方法,将可调用对象从方法中取出并将其作为参数传递,这应该可以解决你的模拟问题。
private static final ExecutorService l = Executors.newFixedThreadPool(1);
private static String getUserInputWithTimeout(int timeout, Callable<String> k) {
LocalDateTime start = LocalDateTime.now();
Future<String> g = l.submit(k);
while (ChronoUnit.SECONDS.between(start, LocalDateTime.now()) < timeout) {
if (g.isDone()) {
try {
String choice = g.get();
return choice;
} catch (InterruptedException | ExecutionException | IllegalArgumentException e) {
logger.error("ERROR", e);
g = l.submit(k);
}
}
}
logger.info("Timeout...");
g.cancel(true);
return null;
}
您的测试应如下所示:
@Test
public void testgetUserInputWithUserInput() throws Exception {
String ENTER = " ";
System.setIn(new ByteArrayInputStream(ENTER.getBytes()));
Callable<String> callable = () -> new Scanner(System.in).nextLine();
assertEquals(ENTER, getUserInputWithTimeout(5, callable));
}