Spock 的多线程代码测试

Multithreading code testing by Spock

我想验证在我的 运行ning 线程之一中抛出的异常。这是我的一段测试代码:

then: 
def e = thrown(RequestFormatException) 
e.message == "Incorrect first line: INCORRECT LINE"

当我 运行 收到下一条消息时:

Exception in thread "Thread-1" by.westside.staircase.core.exception.RequestFormatException: Incorrect first line: INCORRECT LINE 
    at by.westside.staircase.core.util.HttpUtil.parseHttpRequest(HttpUtil.kt:19)
    at by.westside.staircase.core.server.ServerThread.run(ServerThread.kt:26)
    at java.lang.Thread.run(Thread.java:745)

Expected exception of type 'by.westside.staircase.core.exception.RequestFormatException', but no exception was thrown

    at org.spockframework.lang.SpecInternals.checkExceptionThrown(SpecInternals.java:79)
    at org.spockframework.lang.SpecInternals.thrownImpl(SpecInternals.java:66)
    at by.westside.staircase.core.server.SyncServerSpec.should throw exception in incorrect first line case(SyncServerSpec.groovy:26)

thrown(RequestFormatException)

这应该在 then: 之后的第一行,因为这是 spock 施加的约束。

无论何时调用 thrown 或 notThrown 都应该是第一个语句。

注意: thrownnotThrown 都是 return true,因此也不应该有比较运算符。

因此,在您的情况下,应该如下所示:

then: 
 thrown(RequestFormatException) 

Spock 和 JUnit 一样,只能断言从执行测试的线程抛出的异常,而不是 "any thread in the application"。您的异常未被 spock 捕获,无法断言。

您可以使用 Thread.uncaughtExceptionHandler 但您可能应该 unit-test 在您的线程中执行可运行对象 - 或者在您的业务逻辑中实现一些错误处理,并测试这部分代码。

我 运行 遇到了同样的问题,并采取了一条简单的、曲折的路线。本着 "good software is testable software" 的精神,我添加了一个标志并对其进行断言,并将其标记为://仅用于测试。当然,这会在以后被忽略。

我认为另一种选择是实际捕获测试用例中的异常并断言。这是我的代码片段(用 Groovy Spock 编写):

def exceptionThrown = false
def exceptionMessage
def thread = new Thread( {_ ->
   try{
      //code you are testing
   } catch(Exception e) { // change this to the exception you want to catch
      exceptionThrown = true
      exceptionMessage = e.getMessage()
   }
})

then: "the right exception should be thrown"
exceptionThrown
exceptionMessage = "I am thrown" //this should be your error message