복붙노트

[SPRING] Java에서 정적 메서드를 쉽게 조롱 할 수있는 방법 (jUnit4)

SPRING

Java에서 정적 메서드를 쉽게 조롱 할 수있는 방법 (jUnit4)

어떻게하면 Java에서 정적 메서드를 쉽게 조롱 할 수 있습니까?

저는 Spring 2.5와 JUnit 4.4를 사용하고 있습니다.

@Service
public class SomeServiceImpl implements SomeService {

    public Object doSomething() {
        Logger.getLogger(this.class); //a static method invoked.
        // ...
    }
}

내 서비스가 호출해야하는 정적 메서드를 제어하지 않기 때문에 더 단위 테스트 할 수있는 리팩터링을 수행 할 수 없습니다. 예를 들어 Log4J Logger를 사용했지만 실제 정적 메서드는 비슷합니다. 정적 메소드를 변경하는 것은 옵션이 아닙니다.

Grails를 사용하면 다음과 같은 것을 사용하는 데 익숙합니다.

def mockedControl = mockFor(Logger)
mockControl.demand.static.getLogger{Class clazz-> … }
…
mockControl.verify()

Java로 비슷한 것을 어떻게하면됩니까?

해결법

  1. ==============================

    1.호출 코드를 제어 할 수 없다는 것을 의미합니까? static 메소드에 대한 호출을 제어하지만 구현 자체는 제어하지 않기 때문에 쉽게 테스트 할 수 있습니다. 정적 메서드와 동일한 서명을 사용하여 단일 메서드로 종속성 인터페이스를 만듭니다. 프로덕션 구현은 정적 메서드로 호출하지만 현재 정적 메서드를 호출하는 것은 인터페이스를 통해 대신 호출합니다.

    호출 코드를 제어 할 수 없다는 것을 의미합니까? static 메소드에 대한 호출을 제어하지만 구현 자체는 제어하지 않기 때문에 쉽게 테스트 할 수 있습니다. 정적 메서드와 동일한 서명을 사용하여 단일 메서드로 종속성 인터페이스를 만듭니다. 프로덕션 구현은 정적 메서드로 호출하지만 현재 정적 메서드를 호출하는 것은 인터페이스를 통해 대신 호출합니다.

    그런 다음 인터페이스를 정상적인 방법으로 조롱 할 수 있습니다.

  2. ==============================

    2.JMockit 프레임 워크는 정적 메소드의 조롱을 허용합니다.

    JMockit 프레임 워크는 정적 메소드의 조롱을 허용합니다.

    https://jmockit.dev.java.net/

    실제로 정적 메서드가 완벽하게 유효한 디자인 선택이며 테스팅 프레임 워크의 부적절 함으로 인해 해당 메서드의 사용이 제한되어서는 안된다는 등 상당히 과감한 주장이 제기됩니다.

    이러한 주장이 정당화 될 수 있는지 여부에 관계없이 JMockit 프레임 워크 자체는 아직 재미 있지는 않지만 아직 직접 시도하지는 않았습니다.

  3. ==============================

    3.PowerMock에는 이러한 기능이 있습니다. 또한 테스트중인 클래스 내부에서 객체의 인스턴스화를 조롱 할 수 있습니다. 테스트 된 메소드가 새 Foo ()를 호출하면 해당 Foo에 대한 mock 객체를 생성하고 테스트중인 메소드에서이를 대체 할 수 있습니다.

    PowerMock에는 이러한 기능이 있습니다. 또한 테스트중인 클래스 내부에서 객체의 인스턴스화를 조롱 할 수 있습니다. 테스트 된 메소드가 새 Foo ()를 호출하면 해당 Foo에 대한 mock 객체를 생성하고 테스트중인 메소드에서이를 대체 할 수 있습니다.

    억압 생성자와 정적 초기화 자 같은 것들도 가능합니다. 이러한 모든 것은 테스트 할 수없는 코드로 간주되므로 권장되지 않습니다. 그러나 기존 코드가있는 경우 변경하면 항상 옵션이되는 것은 아닙니다. 그 위치에 있다면 PowerMock이 도움이 될 수 있습니다.

  4. ==============================

    4.

    public interface LoggerWrapper {
        public Logger getLogger(Class<?> c);
        }
    public class RealLoggerWrapper implements LoggerWrapper {
        public Logger getLogger(Class<?> c) {return Logger.getLogger(c);}
        }
    public class MockLoggerWrapper implements LoggerWrapper {
        public Logger getLogger(Class<?> c) {return somethingElse;}
        }
    
  5. ==============================

    5.위의 또 다른 대답은 JMockit이 정적 메서드를 모의 할 수 있다는 것입니다.

    위의 또 다른 대답은 JMockit이 정적 메서드를 모의 할 수 있다는 것입니다.

    심지어 로깅 프레임 워크를 직접 지원합니다. 예를 들어 다음과 같이 작성할 수 있습니다.

    
    @UsingMocksAndStubs(Log4jMocks.class)
    public class SomeServiceTest
    {
        // All test methods in this class will have any calls
        // to the Log4J API automatically stubbed out.
    }
    

    그러나 JUnit 4.4에 대한 지원은 중단되었습니다. JUnit 3.8, JUnit 4.5+ 및 TestNG 5.8+가 지원됩니다.

  6. ==============================

    6.그것은 정적 방법이 나쁘다는 이유 중 하나입니다.

    그것은 정적 방법이 나쁘다는 이유 중 하나입니다.

    우리는 대부분의 우리 공장을 재 설계하여 세터 (mter objects)를 설정할 수 있도록합니다. 사실 우리는 하나의 메소드가 모든 싱글 톤을위한 하나의 팩토리로 작동하는 의존성 삽입에 가까운 것을 생각해 냈습니다.

    귀하의 경우, Logger.setLogger () 메소드를 추가하고 (해당 값을 저장하는 것) 작동 할 수 있습니다. 필요한 경우 로거 클래스를 확장하고 자신의 getLogger 메서드를 섀도 잉 할 수 있습니다.

  7. ==============================

    7.AspectJ를 사용하여 정적 메소드 호출을 인터셉트하고 테스트에 유용한 것을 할 수있다.

    AspectJ를 사용하여 정적 메소드 호출을 인터셉트하고 테스트에 유용한 것을 할 수있다.

  8. ==============================

    8.기본적으로 Java + Spring 2.5 및 JUnit 4.4에서이 작업을 수행하는 쉬운 방법은 없습니다.

    기본적으로 Java + Spring 2.5 및 JUnit 4.4에서이 작업을 수행하는 쉬운 방법은 없습니다.

    리팩토링하고 정적 호출을 추상화 할 수는 있지만 리팩토링하는 코드는 내가 찾던 솔루션이 아닙니다.

    JMockit은 작동하는 것처럼 보이지만 Spring 2.5 및 JUnit 4.4와 호환되지 않습니다.

  9. from https://stackoverflow.com/questions/1203027/how-can-i-easily-mock-out-a-static-method-in-java-junit4 by cc-by-sa and MIT license