/* * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot.cli.command; import java.util.EnumSet; import java.util.Set; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.springframework.boot.cli.command.core.HelpCommand; import org.springframework.boot.cli.command.core.HintCommand; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.willThrow; import static org.mockito.Mockito.verify; /** * Tests for {@link CommandRunner}. * * @author Phillip Webb * @author Dave Syer */ public class CommandRunnerTests { @Rule public ExpectedException thrown = ExpectedException.none(); private CommandRunner commandRunner; @Mock private Command regularCommand; @Mock private Command shellCommand; @Mock private Command anotherCommand; private final Set<Call> calls = EnumSet.noneOf(Call.class); private ClassLoader loader; @After public void close() { Thread.currentThread().setContextClassLoader(this.loader); System.clearProperty("debug"); } @Before public void setup() { this.loader = Thread.currentThread().getContextClassLoader(); MockitoAnnotations.initMocks(this); this.commandRunner = new CommandRunner("spring") { @Override protected void showUsage() { CommandRunnerTests.this.calls.add(Call.SHOW_USAGE); super.showUsage(); }; @Override protected boolean errorMessage(String message) { CommandRunnerTests.this.calls.add(Call.ERROR_MESSAGE); return super.errorMessage(message); } @Override protected void printStackTrace(Exception ex) { CommandRunnerTests.this.calls.add(Call.PRINT_STACK_TRACE); super.printStackTrace(ex); } }; given(this.anotherCommand.getName()).willReturn("another"); given(this.regularCommand.getName()).willReturn("command"); given(this.regularCommand.getDescription()).willReturn("A regular command"); this.commandRunner.addCommand(this.regularCommand); this.commandRunner.addCommand(new HelpCommand(this.commandRunner)); this.commandRunner.addCommand(new HintCommand(this.commandRunner)); } @Test public void runWithoutArguments() throws Exception { this.thrown.expect(NoArgumentsException.class); this.commandRunner.run(); } @Test public void runCommand() throws Exception { this.commandRunner.run("command", "--arg1", "arg2"); verify(this.regularCommand).run("--arg1", "arg2"); } @Test public void missingCommand() throws Exception { this.thrown.expect(NoSuchCommandException.class); this.commandRunner.run("missing"); } @Test public void appArguments() throws Exception { this.commandRunner.runAndHandleErrors("command", "--", "--debug", "bar"); verify(this.regularCommand).run("--", "--debug", "bar"); // When handled by the command itself it shouldn't cause the system property to be // set assertThat(System.getProperty("debug")).isNull(); } @Test public void handlesSuccess() throws Exception { int status = this.commandRunner.runAndHandleErrors("command"); assertThat(status).isEqualTo(0); assertThat(this.calls).isEmpty(); } @Test public void handlesNoSuchCommand() throws Exception { int status = this.commandRunner.runAndHandleErrors("missing"); assertThat(status).isEqualTo(1); assertThat(this.calls).containsOnly(Call.ERROR_MESSAGE); } @Test public void handlesRegularExceptionWithMessage() throws Exception { willThrow(new RuntimeException("With Message")).given(this.regularCommand).run(); int status = this.commandRunner.runAndHandleErrors("command"); assertThat(status).isEqualTo(1); assertThat(this.calls).containsOnly(Call.ERROR_MESSAGE); } @Test public void handlesRegularExceptionWithoutMessage() throws Exception { willThrow(new NullPointerException()).given(this.regularCommand).run(); int status = this.commandRunner.runAndHandleErrors("command"); assertThat(status).isEqualTo(1); assertThat(this.calls).containsOnly(Call.ERROR_MESSAGE, Call.PRINT_STACK_TRACE); } @Test public void handlesExceptionWithDashD() throws Exception { willThrow(new RuntimeException()).given(this.regularCommand).run(); int status = this.commandRunner.runAndHandleErrors("command", "-d"); assertThat(System.getProperty("debug")).isEqualTo("true"); assertThat(status).isEqualTo(1); assertThat(this.calls).containsOnly(Call.ERROR_MESSAGE, Call.PRINT_STACK_TRACE); } @Test public void handlesExceptionWithDashDashDebug() throws Exception { willThrow(new RuntimeException()).given(this.regularCommand).run(); int status = this.commandRunner.runAndHandleErrors("command", "--debug"); assertThat(System.getProperty("debug")).isEqualTo("true"); assertThat(status).isEqualTo(1); assertThat(this.calls).containsOnly(Call.ERROR_MESSAGE, Call.PRINT_STACK_TRACE); } @Test public void exceptionMessages() throws Exception { assertThat(new NoSuchCommandException("name").getMessage()) .isEqualTo("'name' is not a valid command. See 'help'."); } @Test public void help() throws Exception { this.commandRunner.run("help", "command"); verify(this.regularCommand).getHelp(); } @Test public void helpNoCommand() throws Exception { this.thrown.expect(NoHelpCommandArgumentsException.class); this.commandRunner.run("help"); } @Test public void helpUnknownCommand() throws Exception { this.thrown.expect(NoSuchCommandException.class); this.commandRunner.run("help", "missing"); } private enum Call { SHOW_USAGE, ERROR_MESSAGE, PRINT_STACK_TRACE } }