2010-05-31 2 views
3

JUnit 테스트에서 나는 이상하게 보일 수없는 문제가 있습니다. 나는 꽤 표준 구조 (DAO의, 서비스 clasess 등 ...)와 다중 모듈 자바 webapp 프로젝트가 있습니다. 이 프로젝트에서 필자는 사용자에게 필요한 항목과 함께 테스트 사용자를 삽입하는 추상화 된 설치 코드를 포함하는 '핵심'프로젝트를 가지고 있습니다 (이 경우 '엔터프라이즈'이므로 사용자는 엔터프라이즈에 속해야하며 강제 적용됩니다 기묘 몇 가지 테스트를 실행하고 사용자가 있기 때문에 삽입 할 수 없습니다 불평 곳 데이터베이스 예외를 발생하지JUnit 테스트가 실패했습니다 - 방금 삽입 된 데이터가 누락되었다고 불평합니다

  1. 을 시작하는 위치를 여기

    가 상당히 지금까지 간단하지만) 데이터베이스 레벨에 엔터프라이즈가 존재하지 않습니다. 하지만 방금 앞선 코드에서 엔터프라이즈를 만들었습니다! 그리고 기업 삽입에 오류가 없었습니다.

  2. 낯선 사람이라면이 테스트 클래스가 자체적으로 실행되면 모든 것이 정상적으로 작동합니다. 테스트가 실패한 프로젝트의 일부로 실행될 때만입니다!
  3. 그리고 똑같은 추상화 된 코드가 실패한 코드보다 10 번의 테스트에 의해 실행되었습니다!
  4. 나는 일이있는 벽에 내 머리를 두드리는 된 정말 어떤 진전을하지 않은

바. 진단 할 때 제공해야 할 정보가 무엇인지 확신 할 수 없습니다. org.apache.commons.dbcp.BasicDataSource에서 org.springframework.jdbc.datasource.DriverManagerDataSource로 전환의 JUnit 4.4, 봄 2.5.6, iBatis를 2.3.0, PostgreSQL을 8.3 사용

    • 문제를 변경했습니다. DriverManagerDataSource를 사용하면 테스트가 처음으로 작동하지만 갑자기 많은 양의 데이터가 데이터베이스에서 롤백되지 않습니다! 그것은 모든 것을 뒤에 남겨 둡니다. 내 문제를 해결하는 데 도움이 될 수있는 어떤 정보를 요청하십시오 이클립스 & 메이븐

    를 통해 실행할 때 오류없이 모든

  • 테스트가 실패합니다!

    업데이트 : 최대 로깅을 설정했습니다. 실패한 테스트와 성공한 테스트 사이에는 약간의 차이가 있습니다. 차이점이 강조 표시됩니다. 오류가 나는 "만들기 [java.util.concurrent.ConcurrentHashMap]"라인의 수 다음 오류 처리 코드는이 하드입니다

  • +0

    오류가 발생했을 때 데이터베이스를 검사 할 수 있습니까? 실제로 기업 기록이 있습니까? – Yishai

    +0

    당신은 DB 모델을 제공 해주십시오. – bragboy

    답변

    0

    글쎄 ...이 문제에 대한 해결책을 찾은 것 같아. 정확하게 내 손가락을 정확히 넣을 수는 없지만. 나는 모든 것을 옮기고 하나씩 복원하여 시험을 재구성하고있었습니다. 낮아서 문제가 다시 나타 났던 마지막 테스트 클래스를 추가하기 전까지는 알 수 없었습니다.

    이 테스트 클래스는 @RunWith 및 @ContextConfiguration과 같은 모든 스프링 관련 설정 주석을 정의한 기본 테스트 클래스에서 확장되었습니다. 어떤 이유로이 테스트 클래스는 @RunWith 및 @ContextConfiguration 특성을 재정의하고 제거하자 마자 다시 작동하기 시작했습니다. 이 테스트 클래스에 대한 또 다른 이상한 점은 @Ignore를 각 테스트에 사용했다는 것입니다 (오래된 테스트가 포함되어 있음). 누군가가이 이상한 문제가있는 경우

    그래서 ... 당신은 내가 Junit4와 스프링을 사용하여 비슷한 문제로 실행

    1

    시작을 볼 발생한 후 문제는 SO에서 해결해야하지만, 나는 당신이 준 세부 사항을 기반으로 야생 추측을 취할 것입니다.

    가설 : 테스트의 삽입물은 모두 트랜잭션에서 발생하며 롤백됩니다. (이 때문에 BasicDataSource는 데이터베이스를 깨끗하게 유지합니다. 결국 다시 롤백됩니다.) 그 일이 (DriverManagerDataSource를 사용하여) 멈 추면 테스트는 통과하지만 데이터베이스는 롤백되지 않습니다.

    "이것은 이전 코드 줄에서 엔터프라이즈를 만들었습니다!"라고 제안합니다. 레코드를 제거하기 위해 트랜잭션을 롤백 할 수 있습니다.

    가설 (정상적인 상태에서 시도해보십시오.), 뭔가 (BasicDataSource 또는 더 많은 고유 한 프레임 워크 코드에서) finalizer에서 트랜잭션의 롤백을 호출합니다. 이것이 10 번 이상 작동 한 다음 프로젝트의 일부로 만 실패한 이유입니다. 그 시점에서 가비지 수집을 트리거하는 실행으로 인해 트랜잭션이 롤백되어 새 줄의 코드가 새 트랜잭션을 시작하게됩니다 레코드가 유효하지 않은 상태입니다.

    편집 : 편집 한 결과, 실패한 테스트에서 어떤 이유로 새로운 데이터베이스 연결이있는 것으로 보입니다. 위의 시나리오와 비슷하지만 테스트가 전체 프로젝트의 일부로 실행될 때 코드의 특정 시점에 새로운 트랜잭션이 발생한다고 설명하면 설명 할 수 있습니다. 새로운 트랜잭션은 다른 트랜잭션에서 발생하는 엔터프라이즈 레코드의 삽입을 보지 않으며 트랜잭션은 공개되어 커밋되지 않은 상태로 유지됩니다. 이를 테스트하는 방법은이 실행시 트랜잭션 격리 수준을 max로 설정하여 트랜잭션이있는 동안 엔터프라이즈 테이블을 검사 할 수있는 것이 없습니다. 이 시나리오가 맞으면 코드가 교착 상태가됩니다.

    또한 편집 : SomeConnectionWrapper 쓰레기 수집과 연결이 닫힌 경우

    public class SomeConnectionWrapper { 
         private Connection dbConnection; 
    
         protected void finalize() { 
          dbConnection.close(); 
         } 
    } 
    

    , 데이터베이스 연결 풀은 다른 연결을 반환합니다 : I 가까이 통화 종료자를 의미하는 무엇이이 같은 것입니다.

    +0

    도움 Yishai 주셔서 감사합니다. 롤백을 트리거하지 않고 트랜잭션을 롤백 할 수있는 방법은 무엇입니까? 즉 오류가 전혀없고 롤백을 트리거하지 않습니다. 필자는 max에 대한 로깅을 증폭 시켰으며 실패한이 테스트와 다른 테스트에서 볼 수있는 차이점이 하나뿐입니다. 나는 그 결과를 잠시 후에 게시 할 것입니다. –

    +0

    @Collin, 내가 말했듯이, 나는 야생 추측 영역에 있습니다. 롤백은 코드에서 다음과 같은 두 가지 방법으로 트리거 될 수 있습니다. 'autocommit : false'로 설정된 데이터베이스 연결 닫기 또는 명시 적으로 롤백. 코드를 검사하여 연결을 닫는 종료자를 확인합니다. – Yishai

    +0

    메인 질문에 게시 된 결과 –

    1

    그것을 해결하기 위해 별도의 주석을 제거 시도 할 수 있습니다. 커밋하기 전에 데이터베이스에서 물건을 다시 읽으려면 테스트 메소드에 @Transactional을 추가해야했습니다.