문제

Java에서 JMock을 사용하여 객체 생성을 모의하는 방법이 있습니까?

예를 들어 다음과 같은 메서드가 있는 경우:

public Object createObject(String objectType) {
    if(objectType.equals("Integer") {
        return new Integer();
    } else if (objectType.equals("String") {
        return new String();
    }
}

...테스트 메서드에서 객체 생성에 대한 기대치를 조롱할 수 있는 방법이 있나요?

나는 유형을 확인하기 위한 추가 코드를 사용하는 대신 특정 생성자가 호출된다는 기대를 걸고 싶습니다(항상 내 예제처럼 복잡하고 단순하지는 않기 때문입니다).

그래서 대신:

assertTrue(a.createObject() instanceof Integer);

특정 생성자가 호출될 것으로 예상할 수 있습니다.조금 더 깔끔하게 만들고 실제로 테스트 중인 내용을 더 읽기 쉬운 방식으로 표현하기 위한 것입니다.

간단한 예를 들어 설명하자면, 제가 작업하고 있는 실제 문제는 좀 더 복잡하지만, 예상을 하면 단순화될 것입니다.


좀 더 자세한 배경 정보를 보려면:

래퍼 개체를 생성하는 간단한 팩토리 메서드가 있습니다.래핑되는 객체에는 테스트 클래스(기존 코드)에서 얻기 어려운 매개변수가 필요할 수 있으므로 구성하기가 어렵습니다.

아마도 내가 실제로 찾고 있는 것에 더 가까운 것은 다음과 같습니다.스텁아웃할 모든 메소드를 지정하지 않고 전체 클래스(CGLib 사용)를 한 번에 모의하는 방법이 있습니까?

따라서 모의 객체는 생성자에 래핑되어 있으므로 메소드가 호출될 수 있습니다. JMock이 각 메소드를 동적으로 모형화할 수 있습니까?

내 추측은 '아니요'입니다. 꽤 복잡할 것이기 때문입니다.하지만 내가 잘못된 나무를 짖고 있다는 것을 아는 것도 가치 있는 일입니다. :-)

도움이 되었습니까?

해결책

내가 생각할 수 있는 유일한 것은 조롱하는 것보다 공장 객체에 create 메소드를 두는 것입니다.

그러나 생성자 호출을 조롱하는 측면에서는 그렇지 않습니다.모의 객체는 객체가 존재한다고 가정하는 반면, 생성자는 객체가 존재하지 않는다고 가정합니다.적어도 할당과 초기화가 함께 발생하는 Java에서는 그렇습니다.

다른 팁

jmockit은 이것을 할 수 있습니다.

내 답변을 참조하세요 https://stackoverflow.com/questions/22697#93675

아아, 제가 잘못된 질문을 한 것은 죄가 있는 것 같습니다.

제가 테스트하려고 했던 간단한 팩토리는 다음과 같았습니다.

public Wrapper wrapObject(Object toWrap) {
    if(toWrap instanceof ClassA) {
        return new Wrapper((ClassA) toWrap);
    } else if (toWrap instanceof ClassB) {
        return new Wrapper((ClassB) toWrap);
    } // etc

    else {
        return null;
    }
}

격리된 테스트에서는 toWrap 개체를 얻기 어렵기 때문에 "new ClassAWrapper( )"가 호출되었는지 어떻게 찾는지 질문하고 있었습니다.그리고 래퍼(그렇게 부를 수 있다면)는 동일한 클래스를 사용하여 다른 객체를 래핑하고 다른 생성자를 사용하기 때문에 좀 이상합니다[1].제가 좀 더 질문을 잘 했다면 다음과 같은 답변을 빨리 받았을 거라 생각합니다.

"다른 테스트 방법에서 테스트 중인 인스턴스와 일치하도록 Object toWrap을 모의해야 하며, 결과 Wrapper 객체를 검사하여 올바른 유형이 반환되었는지 확인해야 합니다.그리고 다른 인스턴스를 만들기 위해 세상을 조롱할 필요가 없을 만큼 운이 좋기를 바랍니다 ;-)"

이제 당면한 문제에 대한 괜찮은 해결책을 찾았습니다. 감사합니다!

[1] 이것이 리팩터링되어야 하는지에 대한 질문을 여는 것은 현재 문제의 범위를 훨씬 벗어납니다 :-)

당신은 익숙합니까? 의존성 주입?

그렇지 않다면, 그 개념에 대해 배우는 것이 확실히 도움이 될 것입니다.내 생각엔 좋은 노인인 것 같아 컨트롤 컨테이너의 반전과 종속성 주입 패턴 Martin Fowler의 훌륭한 소개가 될 것입니다.

DI(종속성 주입)를 사용하면 모든 종류의 클래스를 생성할 수 있는 DI 컨테이너 개체를 갖게 됩니다.그런 다음 개체는 DI 컨테이너를 사용하여 클래스를 인스턴스화하고 DI 컨테이너를 모의하여 클래스가 예상 클래스의 인스턴스를 생성하는지 테스트합니다.

종속성 주입 또는 제어 반전.

또는 생성하는 모든 개체에 대해 Abstract Factory 디자인 패턴을 사용하세요.단위 테스트 모드에 있을 때 무엇을 만들고 있는지 알려주는 테스트 팩토리를 삽입한 다음 테스트 팩토리에 어설션 코드를 포함하여 결과(제어 반전)를 확인합니다.

코드를 최대한 깨끗하게 유지하려면 내부 보호 인터페이스를 생성하고 프로덕션 코드를 내부 클래스로 사용하여 인터페이스(팩토리)를 구현하십시오.기본 팩토리에 초기화된 인터페이스의 정적 변수 유형을 추가합니다.팩토리에 정적 설정자를 추가하면 완료됩니다.

테스트 코드(동일한 패키지에 있어야 하며 그렇지 않으면 내부 인터페이스가 공개되어야 함)에서 어설션 코드와 테스트 코드를 사용하여 익명 또는 내부 클래스를 만듭니다.그런 다음 테스트에서 대상 클래스를 초기화하고, 테스트 팩토리를 할당(주입)하고, 대상 클래스의 메서드를 실행합니다.

아무 일도 없기를 바랍니다.모의는 생성자가 없는 인터페이스를 모의해야 합니다...단지 방법.

여기서 테스트하는 방법에 뭔가 잘못된 것 같습니다.명시적 생성자가 호출되는지 테스트해야 하는 이유가 무엇입니까?
반환된 객체의 유형을 확인하는 것은 팩토리 구현을 테스트하는 데 적합해 보입니다.createObject를 블랙박스로 취급합니다..그것이 무엇을 반환하는지 조사하되 그것이 어떻게 수행되는지 세세하게 관리하지 마십시오.그런 걸 좋아하는 사람은 없어요 :)

업데이트에 대한 업데이트: 아야!절박한 시대에 대한 절박한 대책이죠?JMock이 이를 허용한다면 놀랄 것입니다...내가 말했듯이 인터페이스에서 작동합니다 ..구체적인 유형이 아닙니다.그래서

  • 테스트 하네스에서 성가신 입력 객체를 '인스턴스화'할 수 있도록 노력을 기울이십시오.접근 방식을 상향식으로 진행하세요.
  • 이것이 불가능하다면 중단점을 사용하여 수동으로 테스트해 보십시오(안타깝다는 것을 알고 있습니다).그런 다음 소스 파일의 보이는 영역에 "접촉에 따른 책임은 사용자에게 있습니다"라는 설명을 붙이고 계속 진행하세요.다른 날에도 싸워라.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top