0%

Spock单元测试中针对final static的处理

在做单元测试过程中,我们常常需要对某些字段进行注入Mock

1
2
3
4
5
void reflectSet(Test target, String fieldName, Object value) {
def field = Test.getDeclaredField(fieldName)
field.setAccessible(true)
field.set(target, value)
}

但是有一类数据我们是不方便注入的,例如:

1
2
3
4
5
6
@Slf4j
public class Test {
public void testLog() {
log.info("testLog");
}
}

1
2
3
4
5
6
public class Test {
private final static Logger log = LoggerFactory.get(Test.class);
public void testLog() {
log.info("testLog");
}
}

如果我们需要对log的行为进行测试,那么这里的注入应该怎么搞呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def "test"() {
given:
def log = Mock(Logger)
def test = new Test()
reflectSetFinalStatic(test, "log", log)
when:
service.testLog()
then:
1 * log.info(_) >> {
args->{
assert args[0] == "testLog"
}
}
noExceptionThrown()
}


void reflectSetFinalStatic(Test target, String fieldName, Object value) {
def field = Test.getDeclaredField(fieldName)
field.setAccessible(true)
// 修改访问权限
def modifiers = field.getClass().getDeclaredField("modifiers")
modifiers.setAccessible(true)
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL)
field.set(target, value)
// 恢复访问权限
modifiers.setInt(field, field.getModifiers() & Modifier.FINAL)

}