【问题标题】:Use a real component in a service test在服务测试中使用真实组件
【发布时间】:2019-08-18 03:47:11
【问题描述】:

我正在测试具有自动装配帮助器组件的服务。该组件具有自动装配的 repo。

在我的测试中,我想使用那个组件助手,而不是模拟。我想为此模拟 repo。

但我无法让它工作。

我测试的服务:

@Service
public class ServiceImpl{
    @Autowired
    private Helper helper;
}

具有自动装配 repo 的 Helper 类

@Component
public class Helper {
    @Autowired
    private Repository repo;
}

我的测试应该是这样的

@ExtendWith(MockitoExtension.class)
public class ServiceImplTest {

    ServiceImpl service;

    @Mock
    private Repository repoMock;

    @InjectMocks
    private Helper helper;

}

我想重构整个事情,但不幸的是,这是不可能的......

欢迎任何帮助。

【问题讨论】:

  • Repository 是类还是接口?
  • Repository 是一个接口

标签: java spring mockito junit5


【解决方案1】:

尝试为您的测试加载配置,优先考虑模拟存储库已测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class SomeTest {

    @Configuration
    static class ContextConfiguration {     

        @Bean
        public Helper helper() {
            return new Helper();
        }
        @Bean
        @Primary
        public Repository repoMock() {
            Repo repo = Mockito.mock(Repository.class);
            Mockito.when(/* Mock your repo */);
            return repo;
        }
    }

    @Autowired
    private Helper helper;

    @Test
    public void testMethod() {
        // Your test goes here
    }
}

无论如何,请记住该字段自动装配is evil。尽快切换到构造函数依赖注入。

另请参阅:

【讨论】:

    【解决方案2】:

    我终于找到了解决办法,谢谢你的帮助。

    @ExtendWith(MockitoExtension.class)
    public class ServiceImplTest {
    
        @InjectMocks
        ServiceImpl service
    
        @Spy
        @InjectMocks
        private Helper helper;
    
        @Mock
        private Repository repoMock;
    
        @InjectMocks
        private Helper helper;
    }
    

    这样,mocked repo 被注入到 spy helper 中,而 helper 可以被注入到 service 中。 @Spy 对象实际上是实例化的,所以如果你不存根它的任何方法,你将得到一个“真实”的对象。

    这里,mocked repo 被注入到 helper 中,而 helper 被注入到 service 中。

    【讨论】:

      【解决方案3】:

      如果Repository 是一个接口(而不是具体类),您可以尝试以下操作:

      @ExtendWith(MockitoExtension.class)
      public class ServiceImplTest {
      
          @Spy
          @InjectMocks
          ServiceImpl service = new ServiceImpl();
      
          @Mock
          private Repository repoMock;
      
          @InjectMocks
          private Helper helper;
      }
      

      【讨论】:

      • 问题依旧。在服务中使用 helper 时为 null,因为它没有正确注入(不是模拟)
      • 实际上解决方案与您的解决方案很接近,但它是应该用@Spy注释的助手。
      【解决方案4】:

      我更喜欢构造函数注入而不是字段注入。 (阅读更多here

      在这种情况下,你的类看起来像这样:

          @Component
          public class Helper {
              @Autowired
              public Helper(Repository repo) {
                  this.repo = repo;
              }
          }
      
          @Service
          public class ServiceImpl{
              @Autowired
              public ServiceImpl(Helper helper) {
                  this.helper = helper;
              }
          }
      

      通过这种方式,您可以使用模拟 Repository 对象轻松创建真正的 Helper 对象:

          ServiceImpl service;
      
          private Helper helper;
      
          @Mock
          private Repository repoMock;
      
          @BeforeEach
          void init() {
              helper = new Helper(repoMock);
              service = new ServiceImpl(helper);
          }
      

      【讨论】:

      • 我也更喜欢它,但不幸的是,我无法修改我正在测试的类
      猜你喜欢
      • 2013-10-09
      • 1970-01-01
      • 2015-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多