programing

모키토:개인 필드 초기화 모의

goodjava 2023. 1. 24. 08:13

모키토:개인 필드 초기화 모의

인라인으로 초기화 중인 필드 변수를 어떻게 모킹할 수 있습니까?

class Test {
    private Person person = new Person();
    ...
    public void testMethod() {
        person.someMethod();
        ...
    }
}

여기서 조롱하고 싶다person.someMethod()테스트 중Test.testMethod()초기화를 모의할 필요가 있는 방법person변수.단서는?

편집: 개인 클래스를 수정할 수 없습니다.

Mockito는 반사 보일러 플레이트 코드를 저장하기 위해 도우미 클래스와 함께 제공됩니다.

import org.mockito.internal.util.reflection.Whitebox;

//...

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    Whitebox.setInternalState(underTest, "person", mockedPerson);
    // ...
}

업데이트: 아쉽게도 모키토 팀은 모키토 2의 클래스를 삭제하기로 결정했습니다.이제 다시 리플렉션 보일러 플레이트 코드를 작성하거나 다른 라이브러리(예: Apache Commons Lang)를 사용하거나 Whitebox 클래스(MIT 라이센스)를 도용합니다.

업데이트 2: JUnit 5는 자체 ReflectionSupportAnnotationSupport 클래스와 함께 제공되므로 다른 라이브러리를 가져올 필요가 없습니다.

파티에 꽤 늦었지만, 나는 여기서 충격을 받았고 친구의 도움을 받았다.문제는 PowerMock을 사용하지 않는 것이었다.이것은 최신 버전의 Mockito에서 작동합니다.

모키토는 이것과 함께 나온다org.mockito.internal.util.reflection.FieldSetter.

기본적으로 리플렉션을 사용하여 개인 필드를 수정하는 데 도움이 됩니다.

사용 방법은 다음과 같습니다.

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
    // ...
    verify(mockedPerson).someMethod();
}

이렇게 하면 모의 개체를 전달한 후 나중에 확인할 수 있습니다.

여기 참고 자료가 있습니다.

스프링 테스트를 사용하는 경우 org.springframework.test.util을 사용해 보십시오.반사테스트 유틸리티

 ReflectionTestUtils.setField(testObject, "person", mockedPerson);

저는 여기에 올리는 것을 잊은 이 문제에 대한 해결책을 이미 찾았습니다.

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Test.class })
public class SampleTest {

@Mock
Person person;

@Test
public void testPrintName() throws Exception {
    PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
    Test test= new Test();
    test.testMethod();
    }
}

이 솔루션의 요점은 다음과 같습니다.

  1. Power Mock Runner 테스트 케이스 실행:@RunWith(PowerMockRunner.class)

  2. Powermock에 준비 지시Test.class개인 필드 조작:@PrepareForTest({ Test.class })

  3. 마지막으로 Person 클래스의 컨스트럭터를 조롱합니다.

    PowerMockito.mockStatic(Person.class); PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);

다음 코드를 사용하여 REST 클라이언트 모의에서 매퍼를 초기화할 수 있습니다.mapper필드는 비공개이며 장치 테스트 설정 중에 설정해야 합니다.

import org.mockito.internal.util.reflection.FieldSetter;

new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());

스프링 부트테스트를 사용하고 있는데 어느 쪽도 찾을 수 없는 경우WhiteBox,FeildSetter; 간단하게 사용할 수 있습니다.org.springframework.test.util.ReflectionTestUtils

다음은 예를 제시하겠습니다.

import org.springframework.test.util.ReflectionTestUtils;

//...

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    ReflectionTestUtils.setField(underTestObject, "person", mockedPerson);
    // ...
}

@Jarda의 가이드를 사용하여 변수를 모든 테스트에 대해 동일한 값으로 설정해야 할 경우 다음과 같이 정의할 수 있습니다.

@Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
    FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}

그러나 개인 가치를 다르게 설정하는 것은 신중하게 다루어야 합니다.만약 그들이 사적인 것이라면 어떤 이유에선가.

예를 들어, 단위 테스트에서 수면 대기 시간을 변경할 때 사용합니다.실제 예에서는 10초 동안 자고 싶지만 유닛 테스트에서는 즉시 잠든다면 만족합니다.통합 테스트에서는 실제 값을 테스트해야 합니다.

지금까지의 방법으로는 그게 제일 좋은 것 같아요.

org.springframework.test.util.ReflectionTestUtils

는 지금 합니다.private String mockFieldjavaFooServiceTest.java .java의 FooService.

Foo Service.자바:

  @Value("${url.image.latest}")
  private String latestImageUrl;

FooServiceTest.java:

  @InjectMocks
  FooService service;

  @BeforeEach
  void setUp() {
    ReflectionTestUtils.setField(service, // inject into this object
        "latestImageUrl", // assign to this field
        "your value here"); // object to be injected
  }

언급URL : https://stackoverflow.com/questions/36173947/mockito-mock-private-field-initialization