Spring注入:@MockBean @Repository未注入

Jor*_*rdi 6 spring spring-test spring-boot

我正在尝试@MockBean一个@Repository带注释的课程:

@Repository
public interface ApplicationDao extends MongoRepository<Application, String> {}
Run Code Online (Sandbox Code Playgroud)

我将它注入到带@Service注释的类中:

@Service
public class AuthorizationService {

    private ApplicationDao appsDao;
    private List<Application> allowedApplications;

    @Autowired
    public AuthorizationService(ApplicationDao appsDao) {
        this.appsDao = appsDao;   //<<MOCKED INJECTED BEAN>>
        this.fillApplications();
    }

    private void fillApplications() {
        this.appsDao.findAll()    //<<MOCKED method>>
           .forEach(entry -> {
            this.allowedApplications.put(entry.getName(), entry);
        });
    }

    public bool isAuthorized(Application application) {
        return this.allowedApplications
          .stream()
          .anyMatch(app -> app.getId().equals(application.getId()));
    }
}
Run Code Online (Sandbox Code Playgroud)

我的测试模拟配置如下所示:

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

    private @Autowired AuthorizationService;
    private @MockBean ApplicationDao applicationDao;

    @Before
    public void setUp() {

        Application testApplication = new Application();
        testApplication.setName("test-application");
        List<Application> allowedApplications = new ArrayList<Application>();
        allowedApplications.add(testApplication);

        Mockito
            .when(this.applicationDao.findAll())
            .thenReturn(allowedApplications);
    }

    @Test
    public void test() {
        Application app = new Application();
        app.getId("test-application"); 
        assertTrue(this.authorizationService.isAuthorized(app));  //<<FAILS>>
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,我的模拟对象没有被注入。我的意思是,当我AuthorizationService调用时,它的注入ApplicationDao会返回一个空列表,而不是我的模拟列表。

@MockBean(name="applicationDao")我也尝试过使用。行为是一样的。

我还尝试使用以下代码配置我的模拟 bean:

@TestConfiguration
public class RestTemplateTestConfiguration {

    @Bean("applicationDao")
    @Primary
    public static ApplicationDao mockApplicationDao() {
        ApplicationDao mock = Mockito.mock(ApplicationDao.class);

        Application testApplication = new Application();
        testApplication.setName("test-application");
        List<Application> allowedApplications = new ArrayList<Application>();
        allowedApplications.add(testApplication);

        Mockito
            .when(mock.findAll())
            .thenReturn(allowedApplications);

        return mock;
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,它并不能正常工作。

Application类是:

public class Application {
    private String id;

    //setters & getters
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Bra*_*zic 2

首先要做的事情是测试的类型。答:单元测试。

您正在启动管理生命周期的 Spring 上下文AuthorizationService,然后尝试注入模拟。真正发生的事情是 Spring IoC 容器将真实的ApplicationDao(由 Spring IoC 容器管理的)注入到AuthorizationService.

解决方案:

管理AuthorizationService测试运行程序的生命周期(例如MockitoJUnitRunner并将ApplicationDao模拟注入其中):

@RunWith(MockitoJUnitRunner.class)
public class GroupReferencesTest {

    private @InjectMocks AuthorizationService authorizationService;
    private @Mock ApplicationDao applicationDao;

    @Before
    public void setUp() {

        Application testApplication = new Application();
        testApplication.setName("test-application");
        List<Application> allowedApplications = new ArrayList<Application>();
        allowedApplications.add(testApplication);

        Mockito
            .when(this.applicationDao.findAll())
            .thenReturn(allowedApplications);
    }

    @Test
    public void test() {
        Application app = new Application();
        app.getId("test-application"); 
        assertTrue(this.authorizationService.isAuthorized(app));
    }
}
Run Code Online (Sandbox Code Playgroud)