Last active
August 29, 2015 14:15
-
-
Save janbols/a322699b6b6fe2465e76 to your computer and use it in GitHub Desktop.
memoizing object creation during spock test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import groovy.transform.Immutable | |
@Immutable | |
class User { | |
UUID id | |
String fullName | |
int age | |
} | |
class VeryComplexFilter { | |
int ageThreshold = 40 | |
List<User> lifeStartsAt40(List<User> input) { | |
input.findAll { it.age >= ageThreshold }.sort { it.age } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import spock.lang.Specification | |
import spock.lang.Unroll | |
//@GrabResolver('https://oss.sonatype.org/content/groups/public') | |
//@Grab('org.spockframework:spock-core:0.7-groovy-2.0') | |
//@GrabConfig( systemClassLoader=true ) | |
class UUIDsClutterYourTests extends Specification { | |
@Unroll | |
def "from users with age #inputUsersAge, #resultSize users are kept"() { | |
given: | |
def underTest = new VeryComplexFilter() | |
when: | |
def result = underTest.lifeStartsAt40(input.collect { | |
new User(id: UUID.fromString(it[0]), age: it[1]) | |
}) | |
then: | |
result*.id == expectedResult.collect { UUID.fromString(it) } | |
where: | |
input || expectedResult | |
[["40288045-4BA8-CB2E-014B-A8CB2E780000", 35]] || [] | |
[["40288045-4BA8-CB2E-014B-A8CBA1330002", 41]] || ["40288045-4BA8-CB2E-014B-A8CBA1330002"] | |
[["40288045-4BA8-CB2E-014B-A8CB2E780000", 35], | |
["40288045-4BA8-CB2E-014B-B0C80EDB0003", 52], | |
["40402880-454B-A8CB-2E01-4BB0D5051F00", 15], | |
["40288045-4BA8-CB2E-014B-B0D5CB820005", 79], | |
["40288045-4BA8-CB2E-014B-A8CBA1330002", 41]] || ["40288045-4BA8-CB2E-014B-A8CBA1330002", | |
"40288045-4BA8-CB2E-014B-B0C80EDB0003", | |
"40288045-4BA8-CB2E-014B-B0D5CB820005"] | |
inputUsersAge = input*.get(1) | |
resultSize = expectedResult.size() | |
} | |
static def uuids = (1..10).collect { UUID.randomUUID().toString() } | |
@Unroll | |
def "with predefined uuids, from users with age #inputUsersAge, #resultSize users are kept"() { | |
given: | |
def underTest = new VeryComplexFilter() | |
when: | |
def result = underTest.lifeStartsAt40(input.collect { | |
new User(id: UUID.fromString(it[0]), age: it[1]) | |
}) | |
then: | |
result*.id == expectedResult.collect { UUID.fromString(it) } | |
where: | |
input || expectedResult | |
[[uuids[0], 35]] || [] | |
[[uuids[1], 41]] || [uuids[1]] | |
[[uuids[0], 35], [uuids[3], 52], [uuids[4], 15], [uuids[5], 79], [uuids[1], 41]] || [uuids[1], uuids[3], uuids[5]] | |
inputUsersAge = input*.get(1) | |
resultSize = expectedResult.size() | |
} | |
Closure<?> uuid = { _ -> | |
return UUID.randomUUID() | |
}.memoize() //remember what symbol we mapped to the UUID | |
@Unroll | |
def "with memoized uuids, from users with age #inputUsersAge, #resultSize users are kept"() { | |
given: | |
def underTest = new VeryComplexFilter() | |
when: | |
def result = underTest.lifeStartsAt40(input.collect { | |
def (idChar, age) = it.split('-') | |
new User(id: uuid.call(idChar), age: age as int) | |
}) | |
then: | |
result*.id == expectedResult.collect { uuid.call(it) } | |
where: | |
input || expectedResult | |
["a-35"] || '' | |
["b-41"] || 'b' | |
["a-35", "c-52", "d-15", "e-79", "b-41"] || 'bce' | |
inputUsersAge = input.collect { it.split('-').last() } | |
resultSize = expectedResult.size() | |
} | |
Closure<?> user = { String idAndAge -> | |
def (_, age) = idAndAge.split('-') | |
new User(id: UUID.randomUUID(), age: age as int) | |
}.memoize() //remember what symbol we mapped to the UUID | |
@Unroll | |
def "with memoized users, from users with age #inputUsersAge, #resultSize users are kept"() { | |
given: | |
def underTest = new VeryComplexFilter() | |
when: | |
def result = underTest.lifeStartsAt40(input.collect { user.call(it) }) | |
then: | |
result == expectedResult.collect { user.call(it) } | |
where: | |
input || expectedResult | |
["a-35"] || [] | |
["b-41"] || ['b-41'] | |
["a-35", "c-52", "d-15", "e-79", "b-41"] || ['b-41','c-52', 'e-79'] | |
inputUsersAge = input.collect { it.split('-').last() } | |
resultSize = expectedResult.size() | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import spock.lang.Specification | |
import static TestUtils.* | |
class RememberTest extends Specification { | |
def "remembering symbols to object creation"() { | |
given: | |
remember('complex', { createComplexObject() }) | |
expect: | |
id('a') instanceof UUID | |
id('a') == id('a') | |
id('a') != id('abc') | |
user('a-52') instanceof User | |
user('a-52').age == 52 | |
user('a-52') == user('a-52') | |
user('a-52') != id('a') | |
recall('complex', 'a') == recall('complex', 'a') | |
recall('complex', 'a') != recall('complex', 'b') | |
recall('complex', 'a') != recall('complex', 'abc') | |
recall('complex', 'abc') == recall('complex', 'abc') | |
} | |
def createComplexObject() { | |
return (1..20).collect { UUID.randomUUID() }.groupBy { it.toString().toList().last() } | |
} | |
} | |
class TestUtils { | |
private TestUtils() {} | |
/** | |
* knows how to create objects given a creatorId | |
*/ | |
private static final Map<Object, Closure<?>> creatorRegistry = [ | |
(UUID): { UUID.randomUUID() }, | |
(User): { idAndAge -> | |
def (_, age) = idAndAge.split('-') | |
new User(id: UUID.randomUUID(), age: age as int) | |
} | |
] | |
/** | |
* remembers what object was created given the symbol and the creatorId | |
*/ | |
private static Closure<?> remembers = { String symbol, Object creatorId -> | |
def creator = creatorRegistry[creatorId] | |
assert creator | |
return creator.call(symbol) | |
}.memoize() //remember what symbol we mapped to what created object | |
/** | |
* Registers a creator for a given creatorId | |
* @param creatorId | |
* @param creator | |
*/ | |
static <T> void remember(def creatorId, Closure<T> creator) { | |
assert creatorId | |
assert creator | |
creatorRegistry << [(creatorId): creator] | |
} | |
/** | |
* Recall the object matching the creatorId with the given symbol | |
* @param creatorId | |
* @param symbol | |
* @return | |
*/ | |
static <T> T recall(def creatorId, String symbol) { | |
assert symbol | |
assert creatorId | |
return remembers.call(symbol, creatorId) as T | |
} | |
/** | |
* Generates the same UUID for the same input | |
* @param c | |
* @return | |
*/ | |
static UUID id(String c) { | |
recall(UUID, c) | |
} | |
/** | |
* Generates the same User for the same input | |
* @param idAndAge | |
* @return | |
*/ | |
static User user(String idAndAge) { | |
recall(User, idAndAge) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment