Spring测试:在测试中创建几个类

Spring测试:在测试中创建几个类,spring,unit-testing,spring-test,Spring,Unit Testing,Spring Test,我有一个没有实现类的接口 public interface MyInterface { String getName(); } 我还有另一个类,它将MyInterface作为依赖项 @Component public class SomeClass { @Autowired private MyInterface implementation; public MyInterface someMethod(List<MyInterface>

我有一个没有实现类的接口

public interface MyInterface {
    String getName();
}
我还有另一个类,它将
MyInterface
作为依赖项

@Component
public class SomeClass {
    @Autowired
    private MyInterface implementation;
    
    public MyInterface someMethod(List<MyInterface> list){
        //logic
    }
}
@组件
公共类{
@自动连线
私有接口实现;
公共MyInterface方法(列表){
//逻辑
}
}

我必须测试
SomeClass
,但我没有
MyInterface
实现类。当我可以使用
@Autowired
将它们作为
springbeans
获取时,是否可以在测试中创建一些
MyInterface
实现类,并将它们添加到
ApplicationContext
中?

假设您使用JUnit 5,可以使用
@TestConfiguration
并在那里提供实现:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
class SomeServiceTest {

  @Autowired
  private MyInterface myInterface;

  @TestConfiguration
  static class TestConfig {

    @Bean
    public MyInterface myInterface() {
      
      /**
       * Long version of implementing your interface:
       * 
       *    return new MyInterface() {
       *         @Override
       *         public String getName() {
       *           return null;
       *         }
       *       }; 
       */
      
      // shorter ;-)
      return () -> "Hello World!";
    }
  }

  @Test
  void test() {
    SomeService someService = new SomeService(myInterface);
    System.out.println(someService.doFoo());
  }

}
但您也可以使用Mockito,为您的
MyInterface
创建一个mock,并进行快速单元测试:

@ExtendWith(MockitoExtension.class)
class SomeServiceTest {

  @Mock
  private MyInterface myInterface;

  @InjectMocks
  private SomeService someService;

  @Test
  void test() {
    when(myInterface.getName()).thenReturn("Test");
    System.out.println(someService.doFoo());
  }

}

虽然上面的代码在技术上符合您的要求,但正如J Asgarov在评论中提到的那样,始终考虑这样做是有意义的。

< P>假设您使用JUnit 5,则可以使用<代码> @ TestStase并提供一个实现:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
class SomeServiceTest {

  @Autowired
  private MyInterface myInterface;

  @TestConfiguration
  static class TestConfig {

    @Bean
    public MyInterface myInterface() {
      
      /**
       * Long version of implementing your interface:
       * 
       *    return new MyInterface() {
       *         @Override
       *         public String getName() {
       *           return null;
       *         }
       *       }; 
       */
      
      // shorter ;-)
      return () -> "Hello World!";
    }
  }

  @Test
  void test() {
    SomeService someService = new SomeService(myInterface);
    System.out.println(someService.doFoo());
  }

}
但您也可以使用Mockito,为您的
MyInterface
创建一个mock,并进行快速单元测试:

@ExtendWith(MockitoExtension.class)
class SomeServiceTest {

  @Mock
  private MyInterface myInterface;

  @InjectMocks
  private SomeService someService;

  @Test
  void test() {
    when(myInterface.getName()).thenReturn("Test");
    System.out.println(someService.doFoo());
  }

}

虽然上面的代码在技术上符合您的要求,但正如J Asgarov在评论中提到的那样,始终考虑这样做是有意义的。

这并不能带来任何东西——接口是抽象的,您永远不会测试一个总是测试实现的接口。在测试中创建一些东西只是为了让测试通过,这有什么意义?除非它是一个功能接口,您可以使用lambdas摆脱它,而lambdas使用getName没有任何意义,它不会带来任何东西-接口是一个抽象,否则您永远不会测试接口—您总是测试实现。在测试中创建一些东西只是为了让测试通过,这有什么意义?除非它是一个功能性接口,您可以使用lambdas,而使用getName则没有意义