복붙노트

[SPRING] @Transactional을 가진 @Service에 모의 삽입하는 법

SPRING

@Transactional을 가진 @Service에 모의 삽입하는 법

나는이 단서를 따라 무언가를 가지고있는 단원 테스트에서 어떤 문제가 있습니다. blargh 함수에 Transactional 주석이 달린 경우 모의 주입이 someService에서 오버라이드됩니다. 거래를 제거하면 모의가 거기 머물러 있습니다. 코드를 보았을 때 Spring은 서비스의 함수가 트랜잭션으로 주석을 달았을 때 지연 적으로 서비스를로드하는 것으로 보이지만 그렇지 않은 경우 서비스를 열심히로드합니다. 이것은 제가 주입 한 모의 것을 무시합니다.

이 작업을 수행하는 더 좋은 방법이 있습니까?

@Component
public class SomeTests
{
  @Autowired
  private SomeService someService;

  @Test
  @Transactional
  public void test(){
    FooBar fooBarMock = mock(FooBar.class);
    ReflectionTestUtils.setField(someService, "fooBar", fooBarMock);
  }
}

@Service
public class someService
{
  @Autowired FooBar foobar;

  @Transactional // <-- this causes the mocked item to be overridden
  public void blargh()
  {
    fooBar.doStuff();
  }
}

해결법

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

    1.아마도 다음과 같은 방법으로 테스트를 구현할 수 있습니다.

    아마도 다음과 같은 방법으로 테스트를 구현할 수 있습니다.

    @Component
    @RunWith(MockitoJUnitRunner.class)
    public class SomeTests
    {
      @Mock private FooBar foobar;
      @InjectMocks private final SomeService someService = new SomeService();
    
    
      @Test
      @Transactional
      public void test(){
        when(fooBar.doStuff()).then....;
        someService.blargh() .....
      }
    }
    

    나는 지금 당신의 설정과 관련 코드가 없기 때문에 그것을 시도 할 수 없었다. 그러나 이것이 서비스 논리를 테스트하는 일반적인 방법 중 하나입니다.

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

    2.빈 @Profile 기능을 사용하십시오 - 빈은 특정 그룹과 연관 될 수 있으며, 그룹은 주석을 통해 활성화되거나 비활성화 될 수 있습니다.

    빈 @Profile 기능을 사용하십시오 - 빈은 특정 그룹과 연관 될 수 있으며, 그룹은 주석을 통해 활성화되거나 비활성화 될 수 있습니다.

    보다 자세한 지침은이 블로그 게시물과 문서를 확인하십시오. 이것은 제작 서비스 및 모의 서비스 그룹 두 가지를 정의하는 방법의 예입니다.

    @Configuration
    @Profile("production")
    public static class ProductionConfig {
        @Bean
        public InvoiceService realInvoiceService() {
            ...
        }
        ...
    }
    
    @Configuration
    @Profile("testServices")
    public static class TestConfiguration {
        @Bean
        public InvoiceService mockedInvoiceService() {
            ...
        }
        ...
    }
    
    @Configuration
    @Profile("otherTestServices")
    public static class OtherTestConfiguration {
        @Bean
        public InvoiceService otherMockedInvoiceService() {
            ...
        }
        ...
    }
    

    그리고 이것들을 테스트에 사용하는 방법입니다 :

    @ActiveProfiles("testServices")
    public class MyTest extends SpringContextTestCase {
        @Autowired
        private MyService mockedService;
    
        // ...
    }
    
    @ActiveProfiles("otherTestServices")
    public class MyOtherTest extends SpringContextTestCase {
        @Autowired
        private MyService myOtherMockedService;
    
        // ...
    }
    
  3. from https://stackoverflow.com/questions/21124326/how-to-inject-mock-into-service-that-has-transactional by cc-by-sa and MIT license