@Autowired и UnsatisfiedDependencyException в тесте junit

я пишу тест junit, который должен вызывать какой-то метод из какой-то автоматической зависимости, которая должна взаимодействовать с Cassandra, но я получаю это исключение:

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.21 s <<< FAILURE! - in unicon.mattheews.admin.service.repository.test.AdminUserRepositoryTests
[ERROR] testFindByUsername(unicon.mattheews.admin.service.repository.test.AdminUserRepositoryTests)  Time elapsed: 0.001 s  <<< ERROR!
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'unicon.mattheews.admin.service.repository.test.AdminUserRepositoryTests': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'unicon.matthews.admin.service.repository.AdminUserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
 Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'unicon.matthews.admin.service.repository.AdminUserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Это тест junit:

import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.util.Version;
import org.springframework.test.context.junit4.SpringRunner;

import example.springdata.cassandra.util.CassandraKeyspace;
import unicon.matthews.admin.AdminUser;
import unicon.matthews.admin.service.repository.AdminUserRepository;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = CassandraConfiguration.class)
public class AdminUserRepositoryTests {

@ClassRule public final static CassandraKeyspace CASSANDRA_KEYSPACE = CassandraKeyspace.onLocalhost().atLeast(Version.parse("3.0"));

@Autowired AdminUserRepository repository;

@Before
public void setUp() throws Exception {
    repository.deleteAll();
}

@Test
public void testFindByUsername() {

    try {
        final String userName = "aironman";
        AdminUser.Builder myBuilderAdmin = AdminUser.Builder.class.newInstance();
        myBuilderAdmin.withId("id");
        myBuilderAdmin.withEmailAddress("[email protected]");
        myBuilderAdmin.withOrgId("orgId");
        myBuilderAdmin.withPassword("some-password");
        myBuilderAdmin.withSuperAdmin(Boolean.TRUE);
        myBuilderAdmin.withTenantId("tenantId");
        myBuilderAdmin.withUserName(userName);
        //que viene aqui exactamente?
        Map<String, String> someMetadata = new HashMap<String, String>();
        someMetadata.put("some-key","some-value");
        myBuilderAdmin.withMetadata(someMetadata);
        AdminUser myAdminUser = myBuilderAdmin.build();
        repository.save(myAdminUser);
        Optional<AdminUser> loadedUserName = repository.findByUsername(userName);
        assertNotNull(loadedUserName);
        // assertThat(repository.findOne(homer.id).isPresent(), is(true));
        assertEquals("something went wrong!",userName,loadedUserName.get().getUsername());
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

    System.out.println("Done testFindByUsername!");
}

}

AdminUserRepository выглядит так:

import java.util.Optional;
import org.springframework.data.cassandra.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import unicon.matthews.admin.AdminUser;


@Repository
public interface AdminUserRepository extends CrudRepository<AdminUser, String> {

@Query("select * from AdminUser where username = ?0")
Optional<AdminUser> findByUsername(final String userName);

}

CassandraConfiguration выглядит так:

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;

@Configuration
@EnableAutoConfiguration
class CassandraConfiguration {

@Configuration
@EnableCassandraRepositories
static class CassandraConfig extends AbstractCassandraConfiguration {

    @Override
    public String getKeyspaceName() {
        return "example";
    }

    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.RECREATE;
    }
}

}

Я понимаю, что Spring пытается создать экземпляр этого класса AdminUserRepository, созданного с использованием CrudRepository из проекта spring-data. Предполагается, что если я отмечу этот интерфейс с помощью @Repository, Spring создаст экземпляр класса в контексте Spring, чтобы другой компонент мог автоматически подключить его внутри него, поэтому почему Spring не может создать экземпляр зависимости?

Интерфейс AdminUserRepository находится в src/main/java, а AdminUserRepositoryTests — в src/test/java.

это мой настоящий pom.xml, пожалуйста, помогите.


person aironman    schedule 20.09.2017    source источник
comment
В каких пакетах находятся классы CassandraConfiguration и AdminUserRepository? Конфигурация должна быть корневой для всех остальных классов.   -  person Andriy Slobodyanyk    schedule 20.09.2017
comment
CassandraConfiguration находится в том же пакете, что и AdminUserRepositoryTests, то есть src/test/java/some-package. Зависимость AdminUserRepository находится в src/main/java/another-package. Если я хочу протестировать этот AdminUserRepository, нужно ли мне копировать его в src/test/java/some-package?   -  person aironman    schedule 20.09.2017
comment
Это может быть проблемой. Не возражаете ли вы поместить CassandraConfiguration в src/main/java/some.package? И, как я уже говорил, AdminUserRepository нужно поместить в src/main/java/some.package.another.one/   -  person Andriy Slobodyanyk    schedule 20.09.2017
comment
Вот оно! Теперь я получаю другое исключение: org.springframework.cassandra.support.exception.CassandraInvalidQueryException: unconfigured table adminuser; вложенным исключением является com.datastax.driver.core.exceptions.InvalidQueryException: ненастроенная таблица adminuser, но это для другого вопроса... Я думаю, мне нужно сначала создать таблицу adminuser в выбранном пространстве ключей.   -  person aironman    schedule 20.09.2017


Ответы (1)


Пометка репозитория данных Spring с помощью @Repository на самом деле ничего не делает. Если вы не хотите включать CrudRepository, вам необходимо аннотировать свою конфигурацию с помощью @EnableJpaRepositories. Однако, поскольку вы используете Cassandra, я думаю, что вы, скорее всего, захотите использовать CassandraRepository?

public interface AdminUserRepository extends CassandraRepository<AdminUser, String> {

@Query("select * from AdminUser where username = ?0")
Optional<AdminUser> findByUsername(final String userName);

}
person Plog    schedule 20.09.2017
comment
Да, логичнее использовать интерфейс CassandraRepository вместо CrudRepository. Вы говорите, что я должен пометить свою конфигурацию Cassandra с помощью @EnableJpaRepositories? - person aironman; 20.09.2017
comment
Нет, это было просто для настройки bean-компонента CrudRepository. @EnableCassandraRepositories делает это для CassandraRepository afaik, хотя я сам раньше не использовал Cassandra. - person Plog; 20.09.2017
comment
Если вы посмотрите класс CassandraConfiguration, вы увидите CassandraConfig, который расширяет AbstractCassandraConfiguration, помеченный как Configuration и EnableCassandraRepositories. @Плог - person aironman; 20.09.2017
comment
Да, я знаю, но я думал, что @EnableCassandraRepository не будет работать для CrudRepository, а только для CassandraRepository. Хотя я могу ошибаться. - person Plog; 20.09.2017
comment
расширение интерфейса репозитория с помощью CassandraRepository и использование класса CassandraConfiguration, который должен находиться в том же пакете! Теперь я получаю исключение: com.datastax.driver.core.exceptions.InvalidQueryException: ненастроенный администратор таблицы - person aironman; 20.09.2017
comment
Если честно, я бы задал новый вопрос. По крайней мере, проблема автопроводки Spring теперь решена. - person Plog; 20.09.2017
comment
@Query не требуется при использовании Spring Data Cassandra 1.5. С 1.4 и более ранними версиями это было необходимо. Вам также не нужно расширять CassandraRepository, достаточно CrudRepository. - person mp911de; 20.09.2017