在服务测试中使用真实组件

Use a real component in a service test

我正在测试具有自动装配帮助程序组件的服务。该组件具有自动装配的回购协议。

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

但我无法让它发挥作用。

我测试的服务:

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

具有自动装配 repo

的助手 class
@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 是一个接口(而不是具体的 class),您可以尝试以下操作:

@ExtendWith(MockitoExtension.class)
public class ServiceImplTest {

    @Spy
    @InjectMocks
    ServiceImpl service = new ServiceImpl();

    @Mock
    private Repository repoMock;

    @InjectMocks
    private Helper helper;
}

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

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

    @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);
    }

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

@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。尽快切换到构造函数依赖注入。

另请参阅:

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

@ExtendWith(MockitoExtension.class)
public class ServiceImplTest {

    @InjectMocks
    ServiceImpl service

    @Spy
    @InjectMocks
    private Helper helper;

    @Mock
    private Repository repoMock;

    @InjectMocks
    private Helper helper;
}

这样,模拟的 repo 被注入到间谍助手中,而助手可以被注入到服务中。 @Spy 对象实际上是实例化的,所以如果你不存根它的任何方法,你将得到一个 "real" 对象。

在这里,mocked repo 被注入到 helper 中,helper 被注入到服务中。