我有这堂课:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
class CompliledPatterns {
private static final Map<String, Pattern> compiledPatterns = new ConcurrentHashMap<>();
public static Pattern getPattern(String regex) {
Pattern pattern = null;
if (regex != null) {
pattern = compiledPatterns.get(regex);
if (pattern == null) {
pattern = Pattern.compile(regex);
compiledPatterns.putIfAbsent(regex, pattern);
}
}
return pattern;
}
}
现在我想为此编写测试用例。有什么可能的测试用例?
如果将重复的正则表达式传递给测试类中的getPattern()方法,有什么方法可以验证调用?
答案 0 :(得分:2)
使用static
修饰符来测试方法,您将很难以自然的方式为所有测试设置上下文。
当类加载一次时,您将保持测试方法之间的上下文
并且您需要设置上下文,因为您的类具有状态:compiledPatterns Map
字段。
第一步:删除静态修饰符
private final Map<String, Pattern> compiledPatterns = new ConcurrentHashMap<>();
public Pattern getPattern(String regex) {
Pattern pattern = null;
if (regex != null) {
pattern = compiledPatterns.get(regex);
if (pattern == null) {
pattern = Pattern.compile(regex);
compiledPatterns.putIfAbsent(regex, pattern);
}
}
return pattern;
}
第二步:要进行单元测试,你必须知道被测物体的状态
在调用getPattern()
方法后,您应该有办法检查compiledPatterns Map
字段的内容,以了解您的实施是否已执行它应该执行的操作。
要实现它,您可以提供支持compiledPatterns Map
字段的视图(不可修改的地图)。
public Map<String, Pattern> compiledPatterns getCompiledPatternsView(){
return Collections.unmodifiableMap(compiledPatterns);
}
在断言中,使用它。
例如,对于这个基本场景:当第一次传递正则表达式时,它会缓存在地图中。
测试方法可以是例如:
@Test
public void getPattern_with_first_time_passed_caches_and_returns_the_pattern(){
CompliledPatterns compliledPatterns = new CompliledPatterns();
String regex = "\\s+\\d+";
Assert.assertTrue(compliledPatterns.getCompiledPatternsView().isEmpty());
// action
compliledPatterns.getPattern(regex);
//assertion
Assert.assertEquals(1, compliledPatterns.getCompiledPatternsView().size());
Assert.assertEquals(regex, compliledPatterns.getCompiledPatternsView().get(regex).pattern());
}
答案 1 :(得分:1)
此类的契约是:您将模式提供为字符串,并且该类缓存已编译的模式。因此,请专注于测试合同,而不是特定的实施(恰好使用地图)。
喜欢在:
==
检查模式的相同引用!换句话说:在推动相等字符串时,您希望测试该方法返回相同的模式。所以你可以这样做:
@Test
public void testCachig() {
Pattern first = CompliledPatterns.getPattern("whatever");
Pattern second = CompliledPatterns.getPattern("whatever");
assertThat(first, isSame(second));
}
isSame()是一个检查refential相等的hamcrest匹配器;换一种说法;你assertThat(first == second, is(true))
来这里。
您希望避免检查该类的内部状态。这是一个实现细节。您只关心返回的相同对象。
如果不在您的测试用例中可见,该如何实现。因为那时您可以自由地更改该实现,而无需更改测试用例!并且惊讶:没有使用模拟框架,这个东西完全有效!
我同意davidxxx: static 是一个好的OO异常。它导致紧密耦合并杀死多态性。只有在你有充分理由的情况下才能使用它。