Тест интеграции Spring не может загрузить контекст. Уже существует другой ресурс с именем dataSource.

Я использую тестовую аннотацию, представленную в spring -boot 1.4.3, для своих интеграционных тестов.

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceIT { }

Согласно документации, тестовый контекст кэшируется и повторно используется для ускорения интеграционных тестов. Я хочу именно такого поведения, поскольку инициализация контекста приложения занимает значительное время. Мой отказоустойчивый плагин настроен с

<forkCount>1</forkCount>
<reuseForks>true</reuseForks>

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

Недавно я написал интеграционный тест с использованием аннотации @MockBean для имитации поведения некоторых bean-компонентов.

@RunWith(SpringRunner.class)
@SpringBootTest
public class AnotherServiceIT {
  @MockBean
  SomeService service1
}

Хотя тест работает нормально сам по себе, при запуске через maven verify несколько интеграционных тестов завершаются сбоем с сообщением об ошибке

javax.naming.NamingException: другой ресурс уже существует с именем dataSource - выберите другое имя

Если я пропущу этот конкретный тест с аннотацией JUnit @Ignore, все вернется в норму.

Такое поведение, по-видимому, указывает на то, что использование @MockBean изменяет поведение кэширования, и каждый тест пытается создать свой собственный источник данных. Я также должен упомянуть, что я использую AtomikosDataSourceBean, созданный с помощью XADataSourceAutoConfiguration.

Как я могу решить эту проблему, чтобы мой интеграционный тест мог по-прежнему использовать кешированный контекст и одновременно использовать @MockBean?


person ltfishie    schedule 28.01.2017    source источник
comment
Может быть, это проблема с пружинной загрузкой? github.com/spring-projects/spring-boot/issues/7174   -  person Igor Bljahhin    schedule 02.02.2017
comment
Спасибо, что указали мне на проблему. Я использую spring -boot 1.4.3, и эта проблема должна была быть решена. Я сделаю небольшую отладку, чтобы узнать, так ли это.   -  person ltfishie    schedule 02.02.2017


Ответы (1)


Хм, имеет ли SomeService какое-либо отношение к вашему источнику данных?

Потому что ваш контекст кэширован, а @MockBean делает следующее:

используется для добавления макетов в Spring ApplicationContext ... Любой существующий отдельный bean того же типа, определенного в контексте, будет заменен макетом,

а также

Если существует более одного bean-компонента запрошенного типа, метаданные квалификатора должны быть указаны на уровне поля:

 @RunWith(SpringRunner.class)
 public class ExampleTests {

 @MockBean
 @Qualifier("example")
 private ExampleService service;

Изменить:

Итак, если ваш SomeService является реализацией DataSource, попробуйте добавить Qualifier. Если SomeService имеет в нем DataSource, и вам нужно получить доступ к некоторым его методам, вы можете попробовать использовать @Mock и указать любые объекты, которые необходимо вернуть, либо через их собственный макет, либо через autowire.

@Mock
SomeService someService;

@Mock
SomeDependency mockDependency;

@Autowired
OtherDependency realDependency;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
    doReturn(mockDependency).when(someService).getSomeDependency();
    doReturn(realDependency).when(someService).getOtherDependency();
}
person Tyler Eastman    schedule 07.02.2017