Logger
interface and provide a delegating logger, something similar to LoggerWrapper
, but with a non-final delegate and a setter for updating it. Then in each iteration you could set the new Spock mock as a delegate and then verify interactions on it without using detached mocks or shared fields. Sometimes doing a little bit of development work for a custom mock is better than pulling new dependencies into your project just for testing one thing. The mockStatic
would return the delegating wrapper, of course.
@Delegate
would be even better, I didn't really think it through and/or try. In my time zone I am about to start dinner. But it would be interesting to try later.
@sevenlist Maybe just refactor your ClassThatLogs
into
class ClassThatLogs {
private static final Logger LOG_INSTANCE = LoggerFactory.getLogger(ClassThatLogs.class);
private final Logger log;
ClassThatLogs() {
log = LOG_INSTANCE;
}
ClassThatLogs(Logger logger) {
log = logger;
}
}
And just use the constructor to inject your mocked logger and just use log
instead of LOG_INSTANCE
in the class.
If you don't want to expose it in the constructor you could also use groovys ability to access private fields.
class ClassThatLogs {
private static final Logger LOG_INSTANCE = LoggerFactory.getLogger(ClassThatLogs.class);
private Logger log = LOG_INSTANCE;
}
To modify the log
field from the spec.
IMHO this is much a much cleaner approach then the other variants.
https://twitter.com/spockframework/status/1377558567130107906
We have been advised of a copyright issue with the Spock name, to avoid future problems in this regard we have decided to rebrand. Henceforth, the Spock Framework will be renamed to GWT Framework (Given-When-Then).
Read the full announcement here https://spockframework.org/rebrand-announcement.html
I'm taking a class on Reactive Spring, and I've been able to use Spock no problem so far, but now there's a test using StepVerifier.withVirtualTime()
and it passes no matter what. Here's the whole test:
def "With virtual time"() {
given:
VirtualTimeScheduler.getOrSet()
def longFlux = Flux.interval(Duration.ofSeconds(1))
.take(3)
.log()
expect:
StepVerifier.withVirtualTime({ longFlux.log() })
.expectSubscription()
.thenAwait(Duration.ofSeconds(3))
.expectNext(0L, 1L, 2L)
.verifyComplete()
}
I also don't see the logs from the flux. Any ideas?
withVirtualTime
method, see https://www.baeldung.com/reactive-streams-step-verifier-test-publisher#3-testing-time-based-publishers as an example. Also you don't need VirtualTimeScheduler.getOrSet()
AFAIK.
class Testy extends Specification {
Helper helper = new Helper()
void "testy"() {
expect:
verify()
helper.verify()
}
void verify() {
assert 1 == 2
}
}
class Helper {
void verify() {
assert 1 == 3
}
}
class ClosureTest extends Specification {
Helper helper = new Helper()
void "testy"() {
expect:
verify.call()
}
}
class Helper {
Closure verify= { assert 1 == 2 }
}
runner {
parallel {
enabled true
defaultSpecificationExecutionMode ExecutionMode.SAME_THREAD
defaultExecutionMode ExecutionMode.SAME_THREAD
}
}
DESKTOP-CIDB3LU MINGW64 /e/projects/spock (master)
$ ./gradlew spock-core:test
Configure project :spock-core
[versioning] WARNING - the working copy has unstaged or uncommitted changes.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.8.3/userguide/command_line_interface.html#sec:command_line_warnings
BUILD SUCCESSFUL in 1s
5 actionable tasks: 5 up-to-date
A build scan was not published as you have not authenticated with server 'ge.spockframework.org'.
--no-build-cache
, or change some code locally