2016-08-22 3 views
8

Я разрабатываю инструмент командной строки, который вызывает System.exit() (не хочет использовать исключения вместо) на определенных входах.Scala: Как проверить методы, которые вызывают System.exit()?

Я знаком с Java: How to test methods that call System.exit()? и его самым элегантным approach.

К сожалению, это не достаточно чистым, благодаря мне пришлось добавить зависимости в system-rules, junit-interface

Есть ли общий шаблон для работы с System.exit в specs2, который является более чистым, чем мой текущий подход, который не использовать specs2?

import org.junit.Rule; 
import org.junit.Test; 
import org.junit.contrib.java.lang.system.ExpectedSystemExit; 

public class ConverterTest { 
    @Rule 
    public final ExpectedSystemExit exit = ExpectedSystemExit.none(); 

    @Test 
    public void emptyArgs() { 
     exit.expectSystemExit(); 
     Converter.main(new String[]{}); 
    } 

    @Test 
    public void missingOutArgument() { 
     exit.expectSystemExitWithStatus(1); 
     Converter.main(new String[]{"--in", "src/test/resources/078.xml.gz"}); 
    } 
} 
+1

Проверьте https://groups.google.com/forum/#!topic/scalatest-users/pyKHtcP6HXM, где полезный ответ предлагает Билл Веннерс (автор ScalaTest). –

ответ

6

Если вы действительно хотите, чтобы пойти с помощью метода System.exit(), самый простой способ проверить это было на самом деле называется, чтобы заменить вашу SecurityManager с одним, который будет бросаться ExitException (подклассов SecurityException), когда System.exit() называется:

класс SystemExitSpec

import java.security.Permission 

import org.specs2.mutable.Specification 
import org.specs2.specification.BeforeAfterAll 

sealed case class ExitException(status: Int) extends SecurityException("System.exit() is not allowed") { 
} 

sealed class NoExitSecurityManager extends SecurityManager { 
    override def checkPermission(perm: Permission): Unit = {} 

    override def checkPermission(perm: Permission, context: Object): Unit = {} 

    override def checkExit(status: Int): Unit = { 
    super.checkExit(status) 
    throw ExitException(status) 
    } 
} 


abstract class SystemExitSpec extends Specification with BeforeAfterAll { 

    sequential 

    override def beforeAll(): Unit = System.setSecurityManager(new NoExitSecurityManager()) 

    override def afterAll(): Unit = System.setSecurityManager(null) 
} 

тест ConverterSpec

import org.specs2.execute.Failure 

import scala.io.Source 

class ConverterSpec extends SystemExitSpec { 

"ConverterSpec" should { 

    "empty args" >> { 
     try { 
     Converter.main(Array[String]()) 
     Failure("shouldn't read this code") 
     } catch { 
     case e: ExitException => 
      e.status must_== 1 
     } 
     1 must_== 1 
    } 
} 
+0

Возможно, я пропустил эту часть. Тем не менее, было бы неплохо иметь 'myObject .myFunctionExiting() должен throwAn (ExitException (1)) ' –

+0

Я плохо разбираюсь в specs2. done! – Ven

+0

Извините за беспорядок, вы должны вернуть свое последнее изменение, мы должны использовать ваше предложение, почему? потому что specs2 не проверьте status.code, из-за [реализации] (https://github.com/etorreborre/specs2/blob/master/matcher/src/main/scala/org/sp ecs2/matcher/ExceptionMatchers.scala # L47) –

0

Первый вариант: используйте исключение вместо System.exit.

Второй вариант: вызвать приложение в отдельной цепочке и проверить коды возврата.

Третий вариант: макет System.exit. Есть много возможностей сделать это, упомянув, что это неплохо.

Однако, нет specs2 -специальный образец для работы с System.exit. Лично я бы предложил первый или второй вариант.

+0

1. Первый вариант не подходит для меня. 2. Второй вариант немного переработан для меня и более сложный, чем ** системные правила ** 3. Третий вариант - то же, что и предыдущий IMO, используя ** системные правила **, является кратким, за исключением того, что он не использует ** specs2 ** :( –

+1

Для третьего варианта вы можете использовать насмешливую библиотеку, которая может издеваться над статическими классами, например PowerMock. – dveim