programing

Spring을 통해 주입된 지도 구조 추상 맵퍼에 대한 Junit test 작성 방법

procenter 2023. 9. 27. 19:57
반응형

Spring을 통해 주입된 지도 구조 추상 맵퍼에 대한 Junit test 작성 방법

MapStruct, mapStruct-jdk8 버전 1.1.0을 사용하고 있습니다.스프링을 통해 주입하는 최종적이고 정의적인 추상적인 수업.

Junit Test를 통해 테스트할 수 있는 방법을 찾고 있습니다. 기본적으로 2개의 서브 맵퍼를 사용하는 메인 맵퍼가 있습니다.

@Mapper(componentModel = "spring", uses = {SubMapper1.class, SubMapper2.class})
public abstract class MainMapper {

  @Mapping(target = "field1", qualifiedByName = {"MyMapper2Name", "toEntity"})
  public abstract MyEntity toEntity(MyDto pDto);

  public MyDto fromEntity(MyEntity pEntity) {
     // Specific code, hence why I use Abstract class instead of interface. 
  }
}

여러 가지를 시도해 보았지만 맵퍼를 올바르게 인스턴스화하여 테스트할 수 없습니다.

@RunWith(SpringRunner.class)
public class MainMapperTest {

    private MainMapper service = Mappers.getMapper(MainMapper.class);

    @Test
    public void testToEntity() throws Exception {
.....

자바 lang런타임예외: java.lang.ClassNotFoundException: com.mapers에 대한 구현을 찾을 수 없습니다.메인맵퍼

저도 @InjectMock으로 시도해 보았지만 주사위도 없습니다.

'service'라는 이름의 @InjectMocks 필드를 인스턴스화할 수 없습니다.필드 선언 시 인스턴스를 제공하지 않으셔서 인스턴스를 구성해 보았습니다.그러나 'MainMapper' 유형이 추상 클래스라는 이유로 실패했습니다.

그리고 Spring @Autowired 경유

원인: org.spring framework.콩 공장해당 빈 정의 없음예외:'com.mapers' 유형의 콩이 없습니다.'MainMapper' 사용 가능: 자동 배선 후보에 해당하는 최소 1개의 빈이 필요합니다.종속성 주석: {@org.springframework.콩.공장. annot.자동 연결(필수=true)}

주석 처리 프로세서와 테스트를 시작할 때 맵이 생성되지 않는 것과 관련이 있을 수 있습니다.저는 이 수업을 예로 들었습니다.

그러나 클래스 AnnotationProcessorTestRunner는 아직 최종 릴리스가 없는 1.2 이전에는 사용할 수 없는 것 같습니다.

그래서 제 질문은 제 코드에서 스프링 주입을 통해 사용하는 지도 구조 추상 클래스 맵퍼를 테스트하기 위해 Junit 테스트를 어떻게 작성할 수 있는지 입니다.

@Richard Lewan comment에 대한 응답으로 2개의 subMapper를 사용하여 추상 클래스 ConfigurationMapper에 대한 테스트 클래스를 선언한 방법은 다음과 같습니다.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ConfigurationMapperImpl.class, SubMapper1Impl.class, SubMapper2Impl.class})
public class ConfigurationMapperTest {

당신은 사용합니다.ImplSpringBootTest주석을 단 다음 테스트할 클래스를 주입합니다.

@Autowired
private ConfigurationMapper configurationMapper;

더 많은 정보가 필요하시면 말씀해주시지만, 거기서부터 간단합니다.나는 모든 매핑 과정을 한 번에 테스트하는 것이 더 좋았기 때문에 서브맵퍼를 조롱하지 않았습니다.

답변 추가: @TheBakker 의 대안으로:@SpringBootTest합니다.@ContextConfiguration하지 않은 SpringBoot .그의 예는 다음과 같습니다.

@ExtendWith(SpringExtension.class) // JUnit 5
@ContextConfiguration(classes = {
            ConfigurationMapperImpl.class,
            SubMapper1Impl.class,
            SubMapper2Impl.class
        })
public class ConfigurationMapperTest {
...

JUNIT 를 사용합니다.RunWithExtendWith:

@RunWith(SpringRunner.class)       // JUnit 4
...

모키토 사용:

@Spy
private EntityMapper entityMapper = Mappers.getMapper(MyMapper.class);

예를 들어, 테스트 대상 학급에서 모의실험을 하는 경우 다음과 같은 방법으로 모의실험은 다음과 같습니다.

@InjectMocks
private MyClassUnderTest myClassUnderTest

여러 가지 문제가 있습니다.

  1. 당신은 사용해야 합니다.Mappers#getMapper(Class)componentModel그렇지 요.RuntimeException구현 클래스가 생성되지 않았음을 의미합니다.합니다 설정이 합니다.
  2. 합니다에 합니다.MainMapperImpl그리고 추상적인 계급에 반대하지 않습니다.
  3. 를 .ComponentScan구현 및 사용된 매퍼가 자동으로 배선될 수 있는지 확인합니다.

연결하신 클래스는 잘못된 테스트 클래스이며 테스트 케이스와 관련이 없습니다.스프링 통합을 위한 이 통합 테스트 케이스를 살펴보십시오.

AnnotationProcessorTestRunner는 테스트의 일부이며 주석 처리 프로세서를 테스트하는 데 사용되며 처음부터 사용되었습니다.그것은 릴리스의 일부가 아닙니다.

다음을 가정할 때:

  • 당신의.MainMapper됩니다.@Component ConverterUsingMainMapper

다음 예제를 사용할 수 있습니다.

@RunWith(SpringRunner.class)
@ContextConfiguration
public class ConsentConverterTest {

    @Autowired
    MainMapper MainMapper;

    @Autowired
    ConverterUsingMainMapper converter;

    @Configuration
    public static class Config {

        @Bean
        public ConverterUsingMainMapper converterUsingMainMapper() {
            return new ConverterUsingMainMapper();
        }

        @Bean
        public MainMapper mainMapper() {
            return Mappers.getMapper(MainMapper.class);
        }
    }


    @Test
    public void test1() {
        // ... your test.
    }

}

맵퍼 및 해당 공동작업자와 함께 응용프로그램 컨텍스트를 수동으로 작성할 수도 있습니다.

ApplicationContext context = new AnnotationConfigApplicationContext(MainMapperImpl.class, SubMapper1Impl.class, SubMapper2Impl.class);

아니면

ApplicationContext context = new AnnotationConfigApplicationContext("package.name.for.your.mappers");

그럼 맥락에 따라 맵퍼를 가져오세요.

MainMapper mainMapper = context.getBean(MainMapper.class);

Spring 내에 테스트를 실행하지 않고 이 문제를 해결하고자 하는 모든 사람:

모키토즈를 이용하시면 됩니다.@InjectMock주석 대신 주석을 달았습니다.의 지도 가..FooBarMapper하위 하기, QixSubMapper그리고 당신은 서비스를 테스트하고 있습니다.FooBarService합니까?FooBarMapper을 쓸 입니다:,입니다.

@ExtendWith(MockitoExtension.class)
public class FooBarServiceTest {
    FooBarService fooBarService;
    
    @Mock QixSubMapper qixSubMapper;
    
    @InjectMocks FooBarMapperImpl fooBarMapper;
    
    @BeforeEach
    void setup() {
        fooBarService = new FooBarService(fooBarMapper);
        Mockito.when(qixSubMapper.convert(Mockito.anyString())).thenCallRealMethod();
    }
}

방법입니다. 하는 것입니다. 당신은 당신의 Mapper를 다음과 같이 선언합니다.@InjectMock에 대한 모의를 할 때

그러면 서브 매퍼의 모의가 수행해야 할 작업을 설정하는 것만 하면 됩니다.저 요.@InjectMock법처럼 .@Autowired을 한

100% 효과가 있어요!

@SpringBootTest
 public class CustomMapperTest {

@Spy
private CustomMapper mapper = Mappers.getMapper(CustomMapper.class);

@Test
public void SCENARIO_CONVERT_ACTIVITY() {
    ActivityEntity dbObj = mapper.toDto(ActivityDTO);
    Assert.assertNotNull(dbObj);
    Assert.assertEquals("XXXX", dbobj.getId());
}

@Mapper
public abstract Class CustomMapper{
  @Mapping(source="activityDto.fathername",target="surname")
  public abstract ActivityEntity toDto(ActivityDTO activityDto);
}

맵 구조를 사용하려면 아래를 사용합니다.

Mappers.getMappers(여기에 있는 Mapper Class.class)

예:-

OrderMapper INSTENCE = Mappers.getMapper(OrderMapper.class );

INSTANCE Variable을 사용하고 여기서 맵퍼 클래스 메서드에 액세스합니다.

그리고 SpringRunner.class로 실행합니다.

@RunWith(SpringRunner.class)

임플란트를 찾을 수 없거나 테스트 중인 Test 클래스에서 클래스를 찾을 수 없는 문제가 발견된 경우.그럼 아래와 같이 클린 테스트를 해보세요.

mvn클린테스트

그럼 검사는 괜찮으실 거예요.

참조:-

https://mapstruct.org/development/testing-mapstruct/

언급URL : https://stackoverflow.com/questions/45275382/how-to-write-junit-test-for-mapstruct-abstract-mapper-injected-via-spring

반응형