Есть ли способ использовать конструктор Autowired в тесте JUnit с использованием Spring или Spring Boot? - PullRequest
0 голосов
/ 15 октября 2018

Предположим, что у меня есть тестовая конфигурация с несколькими Spring-компонентами, которые на самом деле смоделированы, и я хочу указать поведение этих макетов в наборе тестов JUnit.

@Profile("TestProfile")
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = {
        "some.cool.package.*"})
public class IntegrationTestConfiguration {

    @Bean
    @Primary
    public Cool cool() {
        return Mockito.mock(Cool.class);
    }
}

// ...

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ActiveProfiles("TestProfile")
public class CoolIntegrationTest {

    private final Cool cool;

    @Autowired
    public CoolIntegrationTest(Cool cool) {
        this.cool = cool;
    }

    @Test
    public void testCoolBehavior {
        when(cool.calculateSomeCoolStuff()).thenReturn(42);
        // etc
    }
}

Если я запускаю этот тест, яполучит:

java.lang.Exception: Test class should have exactly one public zero-argument constructor

Я знаю обходной путь, как использовать поля Autowired в тестах, но мне интересно есть ли способ использовать аннотацию Autowired в тестах JUnit?

Ответы [ 4 ]

0 голосов
/ 15 октября 2018

JUnit требует, чтобы в тестовом примере был конструктор без аргументов, поэтому, поскольку у вас его нет, исключение происходит до процесса подключения.

Так что Constructor-Autowiring просто не работает вэтот случай.

Так что же делать?

Есть много подходов:

Самый простой (так как у вас есть весна) использует аннотацию @MockBean:

@RunWith(SpringRunner.class)
@SpringBootTest
 ....
class MyTest {

   @MockBean
   private Cool cool;

   @Test
   void testMe() {
      assert(cool!= null); // its a mock actually
   }
}
0 голосов
/ 15 октября 2018

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

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ActiveProfiles("TestProfile")
@ContextConfiguration(classes = {IntegrationTestConfiguration.class})
public class CoolIntegrationTest {

    @Autowired
    private final Cool cool;

    @Test
    public void testCoolBehavior {
        when(cool.calculateSomeCoolStuff()).thenReturn(42);
        // etc
    }
}

Аннотация contextConfiguration сообщает Spring, какой конфиг использовать для теста, и автоматическое подключение поля вместо конструктора позволит вам протестироватьтвоя фасоль.

0 голосов
/ 15 октября 2018

Чтобы запустить тест с использованием Spring, необходимо добавить @RunWith(SpringRunner.class) и убедиться, что ваш класс добавлен в путь к классам.Есть несколько способов сделать это.Т.е. добавить класс в конфигурацию MVC @WebMvcTest({Class1.class, Class2.class}) или использовать @ContextConfiguration.

Но я вижу ваш код, я полагаю, что было бы проще просто использовать @Mock или @MockBean для насмешки над вашими бобами.Это будет намного проще.

0 голосов
/ 15 октября 2018

Помимо конструктора args у вас должен быть еще один конструктор без аргументов.Попробуйте добавить его и убедитесь, что это исключение все еще происходит.

@Autowired
public CoolIntegrationTest(Cool cool) {
        this.cool = cool;
    }

public CoolIntegrationTest() {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...