주제 실패
나는 확실히 스레드로부터 안전하지 않습니다 일부 코드가 있습니다테스트 스레드 안전 스팍
public class ExampleLoader
{
private List<String> strings;
protected List<String> loadStrings()
{
return Arrays.asList("Hello", "World", "Sup");
}
public List<String> getStrings()
{
if (strings == null)
{
strings = loadStrings();
}
return strings;
}
}
동시에
null
로
strings
를 볼 것으로 예상된다
getStrings()
, 따라서
loadStrings()
접근
다중 스레드 (비싼 작업 임)가 여러 번 트리거됩니다.
내가 코드 스레드 안전하고 싶었, 세계의 좋은 시민으로서 내가 먼저 실패 스팍 사양을 썼다
문제 :
def "getStrings is thread safe"() {
given:
def loader = Spy(ExampleLoader)
def threads = (0..<10).collect { new Thread({ loader.getStrings() })}
when:
threads.each { it.start() }
threads.each { it.join() }
then:
1 * loader.loadStrings()
}
위의 코드를 생성하고 10 개 스레드를 시작합니다 각 전화 번호는 getStrings()
입니다. 그런 다음 모든 스레드가 완료 될 때 loadStrings()
이 한 번만 호출되었다고 주장합니다.
나는 이것이 실패 할 것으로 예상했다. 그러나 일관되게 통과합니다. 뭐?
System.out.println
및 기타 지루한 것들을 포함하는 디버깅 세션 후에 스레드가 실제로 비동기임을 발견했습니다. run()
메서드가 임의 순서로 인쇄되었습니다. 그러나 getStrings()
에 액세스하는 첫 번째 스레드는 이고 항상은 스레드 인 loadStrings()
스레드입니다. 로, loadStrings()
로 인해 여러 통화를
@Test
public void getStringsIsThreadSafe() throws Exception
{
// given
ExampleLoader loader = Mockito.spy(ExampleLoader.class);
List<Thread> threads = IntStream.range(0, 10)
.mapToObj(index -> new Thread(loader::getStrings))
.collect(Collectors.toList());
// when
threads.forEach(Thread::start);
threads.forEach(thread -> {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// then
Mockito.verify(loader, Mockito.times(1))
.loadStrings();
}
이 테스트는 지속적으로 실패
꽤 많은 시간 동안 디버깅 후
좌절 이상한 부분은 내가 JUnit을 4 Mockito 다시 동일한 테스트를 썼다 예상했다.
가 왜 스팍 테스트를 지속적으로 통과 않고, 내가 스팍으로이 테스트에 대해 어떻게 갈 것이라고 문제?
코드의 테스트를 작성하기 위해 코드의 원래 언어 이외의 다른 것을 사용하려는 이유는 무엇입니까? 자신이 알기에 이것은 디버깅을 악몽으로 만듭니다. 언어가 진행될 수 있고 사랑받는 프레임 워크가 뒤에 남아 있다는 사실 외에도. –
@OlegSklyar Spock/Groovy는 간결하고 빠른 방법으로 대부분의 Java 코드를 테스트 할 수있는 훌륭한 도구입니다. Groovy가 Java 바이트 코드로 컴파일하고 Java 디버거를 사용하는 것이 매우 쉽기 때문에 Spock 프레임 워크 자체의 구현과 관련된 문제라고 생각합니다. 또한, 이것은 작업 상황에서 겪었던 문제에 대한 멍청한 예입니다. Spock/Groovy를 도용하거나 Java에서 기본 코드 기반을 마이그레이션 할 수 없습니다. –
불행히도 저는 원래 질문에 대한 대답이 없기 때문에 저에게 그것은 철학적 토론입니다 ... 그러나 더 이상의 프레임 워크를 도입하면 복잡성이 증가합니다. 그 복잡성으로 지금 당신을 물 렸습니다. 나는 당신이 코드를 리팩터링하기로 결정할 때 아름다운 프레임 워크가 모든 테스트를 리펙토링 할 것이라고 믿는다. 분명히 그렇지 않을 것입니다. 자체 제작 했음에도 불구하고 Java 프로젝트 중 하나에서 비슷한 프레임 워크를 처리해야했습니다. Java 테스트 기반 라이브러리를 작성할 때까지 테스트를 수정하거나 수정하는 것은 악몽이었습니다. 이제 모든 테스트는 이해할 수 있고 리팩토링 할 수 있습니다. –