我正在使用Groovy和Gradle进行测试。
我的应用代码中有以下几行:
Platform.runLater( new Runnable() {
void run() {
....
FileChooser fc = getFileChooser()
File file = fc.showOpenDialog( null )
// if( file != null && file.exists() ) { <--- this is what I have to put
if( file.exists() ) {
println( "file $file exists")
analyseFile( file )
}
如果我嘲笑(使用GroovyMock
,因为javafx.stage.FileChooser
是final
),以便fc.showOpenDialog
返回null
,我希望NullPointerException
成为file.exists()
抛出Runnable
......一个是。
但是这并没有出现在测试结果中,这些结果都是绿色的。你发现这种情况的唯一方法是当你去看看课程的测试结果时:然后你会看到灰色按钮说&#34; StdErr&#34;在场。
这似乎是因为包围Runnable
是&#34;吞咽&#34;它...
Spock有没有办法在def "getting a null result from the showOpenDialog should be handled OK"(){
given:
FileChooser fc = GroovyMock( FileChooser )
ConsoleHandler ch = Spy( ConsoleHandler ){ getFileChooser() >> fc }
ch.setMaxLoopCount 10
systemInMock.provideLines( "o" )
fc.showOpenDialog( _ ) >> null
when:
com.sun.javafx.application.PlatformImpl.startup( {} )
ch.loop()
Thread.sleep( 1000L ) // NB I know this is a rubbish way to handle things... but I'm a newb with Spock!
then:
0 * ch.analyseFile( _ )
}
导致测试失败的情况下做出异常?
PS测试代码:
class ConsoleHandler {
int loopCount = 0
def maxLoopCount = Integer.MAX_VALUE - 1
def response
FileChooser fileChooser = new FileChooser()
void analyseFile( File file ) {
// ...
}
void loop() {
while( ! endConditionMet() ){
print '> '
response = System.in.newReader().readLine()
if( response ) response = response.toLowerCase()
if( response == 'h' || response == 'help' ){
println "Help: enter h for this help, q to quit"
}
else if ( response == 'o' ){
Platform.runLater( new Runnable() {
void run() {
FileChooser fc = getFileChooser()
File file = fc.showOpenDialog( null )
// if( file != null && file.exists() ) {
if( file.exists() ) {
analyseFile( file )
}
}
})
}
}
}
boolean endConditionMet() {
loopCount++
response == 'q' || loopCount > maxLoopCount
}
static void main( args ) {
com.sun.javafx.application.PlatformImpl.startup( {} )
new ConsoleHandler().loop()
com.sun.javafx.application.PlatformImpl.exit()
}
}
这里是应用代码的SSCCE
systemInMock
可能需要解释的唯一另一件事是Spock测试代码中的StdIn
,它允许测试在应用代码中将文本提供给import org.junit.contrib.java.lang.system.TextFromStandardInputStream
import static org.junit.contrib.java.lang.system.TextFromStandardInputStream.emptyStandardInputStream
....
// field of the Test class, of course:
@Rule
public TextFromStandardInputStream systemInMock = emptyStandardInputStream()
:
dependencies
我的Gradle testCompile 'com.github.stefanbirkner:system-rules:1.16.0'
子句中的相应行是:
@Grab
...但我认为这可以通过在Groovy测试文件中使用Platform
来获得,对吧?
我想我现在意识到这个问题真的是关于如何最好地在Spock中进行JavaFX-app线程测试...使用Swing进行EDT测试总是一个问题,毫无疑问类似的事情也适用。它全部回到我身边:当你Runnable
运行runLater
时,当调用者代码移动时从run()
抛出异常是没有意义的,所以我认为唯一可行的选择是export class ChildComponent implements OnInit {
private _foo : Foo;
@Input()
set foo(value : Foo) { this._foo = Object.create(value || null); }
get foo() : Foo { return this._foo; }
@Output() onChange : EventEmitter<Foo> = new EventEmitter<Foo>();
constructor() {
}
ngOnInit() {
}
}
调用测试代码可以调用的其他方法......
我已经搜索过&#34; Spock JavaFX测试&#34;但是没有多少出现......
答案 0 :(得分:0)
这是我想象的唯一实用的前进方式:改变这一点:
else if ( response == 'o' ){
Platform.runLater(new Runnable() {
void run() {
openFileChooser()
}
})
}
ConsoleHandler的新方法:
def openFileChooser() {
FileChooser fc = getFileChooser()
File file = fc.showOpenDialog( null )
// if( file != null && file.exists() ) {
if( file.exists() ) {
analyseFile( file )
}
}
新的Spock测试:
def "getting a null result from the showOpenDialog should be handled OK2"(){
given:
FileChooser fc = GroovyMock( FileChooser )
ConsoleHandler ch = Spy( ConsoleHandler ){ getFileChooser() >> fc }
fc.showOpenDialog( _ ) >> null
when:
com.sun.javafx.application.PlatformImpl.startup( {} )
ch.openFileChooser()
Thread.sleep( 1000L )
then:
0 * ch.analyseFile( _ )
}
测试失败(欢呼!):
java.lang.NullPointerException:无法在null上调用exists()方法 对象
但我欢迎来自更有经验的Groovy / Spock手的改进是否可以改进。
确实我有点疑惑为什么我没有得到错误的状态&#34;当我在openFileChooser
子句中调用when:
时。我认为这是因为在模拟 showOpenDialog
上进行FileChooser
实际上并不涉及任何检查,以确保我们目前在JavaFX-app-中线。事实证明,在该测试中可以删除...PlatformImpl.startup( {} )
和Thread.sleep
行。这是理想的做法吗?!嗯...
<强> 后 强>
将此视为唯一的答案......实际上,在JavaFX-app-thread中使用普通的JUnit测试普通旧Java中的代码时,同样的注意事项也适用于此问题。 Spock + Groovy可能会带来一些问题,或者可能会让它变得更容易......我还没有足够的经验让他们知道。