Java 测试中的Spring启动覆盖接口

Java 测试中的Spring启动覆盖接口,java,testing,spring-boot,Java,Testing,Spring Boot,我有一个springboot应用程序(v1.3.5) 我的主要应用是: @SpringBootApplication @ComponentScan({"com.akrome"}) public class InboxCoreApplication { public static void main(String[] args) { SpringApplication.run(InboxCoreApplication.class, args); } } 在包中的某

我有一个springboot应用程序(v1.3.5)

我的主要应用是:

@SpringBootApplication
@ComponentScan({"com.akrome"})
public class InboxCoreApplication {
    public static void main(String[] args) {
        SpringApplication.run(InboxCoreApplication.class, args);
    }
}
在包中的某个地方,我将回购定义为一个实现:

@Repository
public class CouchbaseServiceImpl implements CouchbaseService {
在其他地方,我有一个使用该接口的类:

@Repository
public class InboxObjectRepositoryImpl {
    @Autowired
    private CouchbaseService couchbaseService;
@Repository
public class CouchbaseServiceTestImpl implements CouchbaseService {
我还有一个接口的测试版本:

@Repository
public class InboxObjectRepositoryImpl {
    @Autowired
    private CouchbaseService couchbaseService;
@Repository
public class CouchbaseServiceTestImpl implements CouchbaseService {
现在。在我的测试中,我想简单地将接口映射重新指向测试实现,同时保留主配置组件扫描定义的所有其他内容。但它一直在发疯。我得到的最接近的结果是:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {InboxCoreApplication.class, TestConfig.class})
public class InboxServiceTest {
    @Autowired
    CouchbaseServiceTestImpl couchBaseServiceTestImpl;
其中TestConfig是:

@Configuration
public class TestConfig {
    CouchbaseServiceTestImpl couchbaseServiceTestImpl = new CouchbaseServiceTestImpl();

    public CouchbaseService couchbaseService() {
        return couchbaseServiceTestImpl;
    }
}
但是每次它要么抱怨重复的bean(bc它看到了两个实现),要么注入了测试实现的两个不同实例,一个在测试类中,一个在实际程序中(wat?)


有什么建议吗?

我想你的问题在于下面的课程。为什么要重新实现CouchbaseService接口并将其作为测试版本。这样做的真正意义是什么?应该开发单元测试类来测试主源的功能。您正在创建该源类的测试版本,并创建单元测试来测试该测试版本。这样做有什么意义

@Repository
public class CouchbaseServiceTestImpl implements CouchbaseService {
因此,更好的实现应该是删除CouchbaseServiceTestImpl类。编写单元测试以直接测试CouchbaseServiceImpl。(您还可以删除TestConfig类)

所以代码应该是这样的

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {InboxCoreApplication.class})
public class InboxServiceTest {

    @Autowired
    CouchbaseServiceImpl  couchbaseServiceImpl ;
抱怨复制bean的真正原因可以描述如下

@Repository("couchbaseServiceTestImpl")
public class CouchbaseServiceTestImpl implements CouchbaseService {
如果您用@Repository、@Component或@Service注释了任何类,那么spring IOC容器将自动实例化这些类,并在加载spring应用程序上下文时在应用程序上下文中注册

因此,您有两个CouchbaseService接口的实现。 1.CouchbaseServiceImpl 2.CouchbaseServiceTestImpl

由于这两个类都使用@Repository进行了注释,因此spring应用程序容器将实例化这两个类,并在IOC容器中维护这两个对象。这两个实例都可以分配给CouchbaseService接口引用

请看代码中的以下行

  @Autowired
  private CouchbaseService couchbaseService;
现在,spring应用程序容器在查找相关匹配bean(是否应该使用CouchbaseServiceImpl或CouchbaseServiceTestImpl。这两个bean都符合分配条件)方面遇到了问题。因此,它会发出重复警告,不会执行分配

你有两个选择

选项01。 删除其中一个类中的@Repository注释。最好在CouchbaseServiceTestImpl中移除它。(如我前面所述,最好删除该类)

选项02 让所有的课程都按照你的要求进行。user@Qualifier告诉spring应用程序容器分配的真正匹配bean

因此,代码应按如下所示进行更改

@Repository("couchbaseServiceTestImpl")
public class CouchbaseServiceTestImpl implements CouchbaseService {


所以它将把CouchbaseServiceTestImpl的一个实例分配给CouchBaseServiceReference。

我想我找到了它

它应该是用户配置文件:

@Repository
@Profile("application")
public class CouchbaseServiceImpl implements CouchbaseService {

在我的测试中,我只是:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {InboxCoreApplication.class})
@ActiveProfiles("test")
public class InboxObjectRepositoryImplTest {

您可以在这里添加堆栈跟踪吗?很有意义,您有
CouchbaseServiceTestImpl
和CouchbaseServiceImpl`这两个都是由Spring容器为您的测试加载的。一个是由于
TestConfig
而加载的,另一个是由于您导入了
InboxCoreApplication
,该应用程序会自动对每个子包进行组件扫描。原因是,这不是我正在测试的。这是一个DB连接对象,当我测试应用程序的其余部分时,我不想连接到DB,只需要使用内存中的模拟。但是我看到了你的观点,但这对我没有帮助,因为注入bean的其他类将无法使用它,因为它们用于非测试命名版本:/