Не удается выполнить автосопровождение в тесте JUnit 4 в мультимодульном приложении Spring Boot - PullRequest
0 голосов
/ 13 января 2020

У меня следующая структура проекта:

-module1
--src/main/java/at.flobau.demo.module1
---model
----Product.java
---service
----ProductService.java
---TestConfiguration.java

--src/test/java/at.flobau.demo.module1.service
---ProductServiceTest.java

-module2
--src/main/java/at.flobau.demo.main
---MainApplication.java

Класс Application выглядит следующим образом:

@SpringBootApplication(scanBasePackages = {"at.flobau.demo.main"})
@PropertySource(value = "classpath:application.properties")
@EnableJpaRepositories("at.flobau.demo.module1")
@EntityScan(basePackages = {"at.flobau.demo.module1"})
public class PocApplication {

    public static void main(String[] args) {
        SpringApplication.run(PocApplication.class, args);
    }

}

Служба выглядит следующим образом:

@Service
public class ProductService implements IProductService {

    @Autowired
    private IProductRepository productRepository;

    ...
}

Тестовый класс выглядит например:

@SpringBootTest
@ContextConfiguration(classes = { TestConfiguration.class }, loader = 
AnnotationConfigContextLoader.class)
@RunWith(SpringRunner.class)
public class ProductServiceTest {

    @Autowired
    private ProductService productService;

    ...
}

Файл конфигурации теста выглядит следующим образом:

@Configuration
@ComponentScan("at.flobau.demo")
public class TestConfiguration{ }

IntelliJ сообщает мне, что ProductService внутри теста не может быть подключен автоматически. Когда я запускаю тест, я получаю исключение:

Error creating bean with name 'ProductServiceTest': Unsatisfied dependency expressed through field 
'productService'; nested exception is 
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 
'at.flobau.demo.module1.products.service.ProductService' available: expected at least 1 bean which 
qualifies as autowire candidate. Dependency annotations: 
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

Ответы [ 3 ]

1 голос
/ 13 января 2020

Вы можете аннотировать свой тестовый класс с помощью @SpringBootTest(classes = ProductService.class)

1 голос
/ 14 января 2020

Вы должны избегать использования инъекции поля (даже если это возможно) и использования инжектора конструктора. Это решит эту проблему, поскольку вы сможете передавать службу из конструктора, но это также будет полезно в будущем, поскольку вы сможете находить объекты и отслеживать объекты в своем коде лучше, чем инъекции полей, которые «скрыты»

Поэтому я рекомендую вместо того, чтобы пытаться решить вашу проблему здесь, провести рефакторинг вашего класса в инжекторе конструктора и передать сервис оттуда либо путем непосредственного создания объекта в вашем тесте, либо путем создания конфигурации для вашего теста, которая будет генерировать объект и приведите аргументы

что-то вроде

@ContextConfiguration(classes = { GeneralTester.TestConfig.class })
@RunWith(SpringRunner.class)
public class GeneralTester {
  @TestConfiguration
  public static class TestConfig {
    @Bean
    public IProductService productService(final IProductRepository productRepository){
     return new ProductService(productRepository);
    }
    @Bean
    public IProductRepository productRepository(){
      return mock(IProductRepository.class);
    }
  }

  @Autowire
  public IProductService productService;

  @Autowire
  public IProductRepository productRepository;

  @Before
  public void setUp() {
    reset(productRepository);
  }

  @After
  public void tearDown() {
    verifyNoMoreInteractions(productRepository);
  }

  @Test
  public void doSmth() {
    //... your setup
    when(productRepository.save(any())).thenReturn("something");
    //... your call and assertions
    verify(productRepository).save(any());
  }
}
0 голосов
/ 13 января 2020

Вы пытались создать компонент службы в классе конфигурации теста?

@TestConfiguration
@ComponentScan("at.flobau.demo")
public class TestConfiguration { 
    @Bean
    public ProductService productService() {
        return new ProductService();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...