복붙노트

[SPRING] 팩토리 클래스에 의해 생성 된 객체에 대한 모의 객체 삽입

SPRING

팩토리 클래스에 의해 생성 된 객체에 대한 모의 객체 삽입

저는 다음과 같은 수업을 듣습니다 :

public class MyClass {        
    private Apple apple;

    public void myMethod() {
       apple = AppleFactory.createInstance(someStringVariable);
       ....
       ....
       ....
    }
}

그리고 Test 클래스 :

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {

        @InjectMocks 
        MyClass myClass;

        @Test
        public void myMethod(){
         ...
         ...
         ...
        }
    }

MyClass에 모의 사례로 Apple 인스턴스를 삽입하려면 어떻게해야합니까?

해결법

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

    1.이 문제를 해결할 수있는 가능성은 3 가지입니다.

    이 문제를 해결할 수있는 가능성은 3 가지입니다.

    추상 팩토리 : 정적 메서드를 사용하는 대신 구체적인 팩토리 클래스를 사용하십시오.

    public abstract class AppleFactory {
        public Apple createInstance(final String str);
    }
    
    public class AppleFactoryImpl implements AppleFactory {
        public Apple createInstance(final String str) { // Implementation }
    }
    

    테스트 클래스에서 팩토리를 조롱하세요 :

    @RunWith(MockitoJUnitRunner.class)
    public class MyClassTest {
    
        @Mock
        private AppleFactory appleFactoryMock;
    
        @Mock
        private Apple appleMock;
    
        @InjectMocks 
        MyClass myClass;
    
        @Before
        public void setup() {
            when(appleFactoryMock.createInstance(Matchers.anyString()).thenReturn(appleMock);
        }
    
        @Test
        public void myMethod(){
         ...
         ...
         ...
        }
    }
    

    PowerMock : PowerMock을 사용하여 정적 메서드 모의 개체를 만듭니다. 관련 질문에 대한 내 대답을보고 어떻게 완료되었는지 확인하십시오.

    테스트 가능한 클래스 : Apple 생성을 보호 된 메서드로 래핑하고이를 오버라이드하는 테스트 클래스를 만듭니다.

    public class MyClass {
       private Apple apple;
    
       public void myMethod() {
           apple = createApple();
           ....
           ....
           ....
       }
    
       protected Apple createApple() {
           return AppleFactory.createInstance(someStringVariable);
       }
    }
    
    
    @RunWith(MockitoJUnitRunner.class)
    public class MyClassTest {
    
        @Mock
        private Apple appleMock;
    
        @InjectMocks 
        MyClass myClass;
    
        @Test
        public void myMethod(){
         ...
         ...
         ...
        }
    
        private class TestableMyClass extends MyClass {
           @Override
           public void createApple() {
              return appleMock;
           }
        }
    }
    

    물론, 테스트 클래스에서는 MyClass가 아닌 TestableMyClass를 테스트해야합니다.

    나는 각각의 방법에 대한 제 의견을 말씀 드리겠습니다 :

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

    2.Avi & Ev0oD의 첫 번째 답변 추상 클래스는 확장 만 가능하며 구현되지 않습니다.

    Avi & Ev0oD의 첫 번째 답변 추상 클래스는 확장 만 가능하며 구현되지 않습니다.

      public abstract class AppleFactory {
        public abstract Apple createInstance(final String str);
    }
    
    public class AppleFactoryImpl extends AppleFactory {
        public Apple createInstance(final String str) { // Implementation }
    }
    
  3. ==============================

    3.Avi가 제안한 솔루션 외에도 다음과 같은 네 가지 가능성을 선택할 수 있습니다.

    Avi가 제안한 솔루션 외에도 다음과 같은 네 가지 가능성을 선택할 수 있습니다.

    공장에 주입 : 이것은 나를 위해 리팩토링 할 코드가 이미있는 경우 가장 좋은 옵션입니다. 이 솔루션을 사용하면 생산 코드를 변경하지 않고 공장 클래스와 테스트 만 변경할 수 있습니다.

    public class AppleFactory
    {
        private static Apple _injectedApple;
    
        public static createInstance(String str)
        {
            if (_injectedApple != null)
            {
                var currentApple = _injectedApple;
                _injectedApple = null;
                return currentApple;
            }
    
            //standard implementation
        }
    
        public static setInjectedApple(Apple apple)
        {
            _injectedApple = apple;
        }
    }
    

    이제 정적 팩토리를 간단하게 사용할 수 있습니다.

    @RunWith(MockitoJUnitRunner.class)
    public class MyClassTest {
    
        @Mock
        private Apple appleMock;
    
        @InjectMocks 
        MyClass myClass;
    
        @Before
        public void setup() {
            AppleFactory.setInjectedApple(appleMock);
        }
    
        @Test
        public void myMethod(){
         ...
         ...
         ...
        }
    }
    
  4. from https://stackoverflow.com/questions/21879804/inject-mocks-for-objects-created-by-factory-classes by cc-by-sa and MIT license