programing

@InjectMocks를 사용하여 String 속성 주입

jooyons 2023. 9. 27. 17:55
반응형

@InjectMocks를 사용하여 String 속성 주입

스프링 MVC가 있습니다.@Controller이 시공자와 함께:

@Autowired
public AbcController(XyzService xyzService, @Value("${my.property}") String myProperty) {/*...*/}

이 컨트롤러에 대해 독립 실행형 장치 테스트를 작성하려고 합니다.

@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {

    @Mock
    private XyzService mockXyzService;

    private String myProperty = "my property value";

    @InjectMocks
    private AbcController controllerUnderTest;

    /* tests */
}

다른 방법이 없을까요?@InjectMocks내 String 속성을 주입하라고요?String은 불변이기 때문에 조롱할 수 없다는 것을 알지만, 여기에 그냥 일반 String을 주입해도 될까요?

@InjectMocks이 경우 기본적으로 null을 주입합니다.@Mock내가 예외를 적용한다면 이해할 수 있습니다.myProperty. 제가 놓친 주석 중에 "이 정확한 객체를 조롱하는 것이 아니라 주입하라"는 의미의 주석이 또 있습니까?

모키토로 할 수는 없지만 Apache Commons는 내장된 유틸리티 중 하나를 사용하여 이를 수행할 수 있는 방법이 있습니다.Mockito가 나머지 모의실험을 주입한 후 테스트 케이스가 실행되기 전에 Junit에서 실행되는 함수에 이 함수를 넣을 수 있습니다.

@InjectMocks
MyClass myClass;

@Before
public void before() throws Exception {
    FieldUtils.writeField(myClass, "fieldName", fieldValue, true);
}

Spring을 사용하고 계시기 때문에.org.springframework.test.util.ReflectionTestUtils로부터spring-test모듈.객체에 필드를 설정하거나 클래스에 정적 필드를 설정할 때(다른 유틸리티 메서드와 함께) 깔끔하게 래핑합니다.

@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {

    @Mock
    private XyzService mockXyzService;

    @InjectMocks
    private AbcController controllerUnderTest;

    @Before
    public void setUp() {
        ReflectionTestUtils.setField(controllerUnderTest, "myProperty", 
               "String you want to inject");
    }

    /* tests */
}

모키토를 이용해서는 안 돼요 왜냐면 당신 말대로Stringfinal조롱할 수 없습니다

있습니다.@Spy실제 물체에 작용하는 주석이지만 다음과 같은 한계를 가지고 있습니다.@Mock, 따라서 당신은 당신이 a를 염탐할 수 없습니다.String.

모키토에게 조롱이나 스파이 행위를 하지 않고 그 가치를 주입하라고 말할 주석은 없습니다.그래도 좋은 기능이 될 것 같습니다.아마도 모키토 깃허브 저장소에서 제안해 보세요.

코드를 변경하지 않으려면 컨트롤러를 수동으로 인스턴스화해야 합니다.

순수 주석 기반 테스트를 수행할 수 있는 유일한 방법은 컨트롤러를 리팩터하는 것입니다.속성 하나만 포함하는 사용자 지정 개체를 사용하거나 속성이 여러 개인 구성 클래스를 사용할 수도 있습니다.

@Component
public class MyProperty {

    @Value("${my.property}")
    private String myProperty;

    ...
}

이것은 컨트롤러에 주입될 수 있습니다.

@Autowired
public AbcController(XyzService xyzService, MyProperty myProperty) { 
    ... 
}

그러면 이걸 조롱하고 주사를 놓으시면 됩니다.

@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {

    @Mock
    private XyzService mockXyzService;

    @Mock
    private MyProperty myProperty;

    @InjectMocks
    private AbcController controllerUnderTest;

    @Before
    public void setUp(){
        when(myProperty.get()).thenReturn("my property value");
    }

    /* tests */
}

이것은 아주 간단하지는 않지만, 적어도 약간의 스텁(stub)이 있는 순수한 주석 기반의 테스트를 가질 수 있을 것입니다.

그런 경우에는 @InjectMocks를 사용하지 마십시오.

행:

@Before
public void setup() {
 controllerUnderTest = new AbcController(mockXyzService, "my property value");
}

솔루션은 간단합니다.개체 유형에 대해 생성자 주입을 수행해야 하지만 원시/최종 종속성의 경우 설정자 주입을 사용하면 됩니다. 이 시나리오에서는 괜찮습니다.

그래서 이것은:

public AbcController(XyzService xyzService, @Value("${my.property}") String myProperty) {/*...*/}

다음으로 변경됨:

@Autowired
public AbcController(XyzService xyzService) {/*...*/}

@Autowired
public setMyProperty(@Value("${my.property}") String myProperty){/*...*/}

.@Mock시험 시 주사는 다음과 같이 간단합니다.

@Mock
private XyzService xyzService;

@InjectMocks
private AbcController abcController;

@BeforeMethod
public void setup(){
    MockitoAnnotations.initMocks(this);
    abcController.setMyProperty("new property");
}

그 정도면 충분합니다.> ㅇㅇReflections권장되지 않습니다!

생산코드에 리플렉션이 사용되는 것을 최대한 피하시기 바랍니다!!

.Jan Groot다를 해야 하기 에 매우 .@Mock@InjectMocks그리고 초기화한 후 수동으로 주입해야 합니다. 2개의 의존성의 경우 쉽게 들리지만 7개의 의존성의 경우 코드가 악몽이 됩니다(아래 참조).

private XyzService xyzService;
private AbcController abcController;

@BeforeMethod
public void setup(){ // NIGHTMARE WHEN MORE DEPENDENCIES ARE MOCKED!
    xyzService = Mockito.mock(XyzService.class);
    abcController = new AbcController(xyzService, "new property");
}

사용할 수 있는 것은 org.mockito 입니다.내부의 util, 반사화이트박스

  1. "AbcController" 클래스 생성기 리팩터
  2. Test class "before" 메서드에서 Whitebox.setInternalState 메서드를 사용하여 원하는 문자열을 지정합니다.

    @Before
    public void setUp(){
        Whitebox.setInternalState(controllerUnderTest, "myProperty", "The string that you want"); }
    

코드를 변경하지 않으려면 Reflection을 사용합니다.TestUtils.setField 메서드 Mockito로 봄에 자동으로 연결된 @Value 필드를 mocking하려면 어떻게 해야 합니까?

TL;DR

@Autowired
@InjectMocks
private AbcController controllerUnderTest;

설명:얼마나 간단하면서도 까다로웠는지 알면 놀랄 것입니다.@Autowired@InjectMock 주석을 함께 사용해 보십시오.

이를 통해 실제 개체가 먼저 로드되고 스파이나 조롱이 필요한 개체가 주입됩니다.실제 개체는 속성을 통해 이미 입력된 값을 갖게 됩니다.

언급URL : https://stackoverflow.com/questions/36084559/injecting-a-string-property-with-injectmocks

반응형