java模拟服务函数未按预期工作

dw1jzc5e  于 2021-07-13  发布在  Java
关注(0)|答案(1)|浏览(348)

这是我的密码。我不明白为什么它不起作用。问题在于线路输入测试:

when(applicationUserRepository.findApplicationUserByUsername("testUser"))
        .thenReturn(userToReturnFromRepository);

似乎什么都没做。当函数findapplicationuserbyusername应该返回usertoreturnfromrepository的可选值时,它返回一个空的可选值。
控制器:

@RestController
@RequestMapping("api/v1/exercises")
public class ExerciseController {

    @Autowired
    ExerciseService exerciseService;

    @GetMapping
    public List<Exercise> getExercises() {

        List<Exercise> exercises = exerciseService.getAllExercises();
        return exercises;
    }
}

服务:

@Service("exerciseService")
public class ExerciseService {

    @Autowired
    ExerciseRepository exerciseRepository;

    @Autowired
    ApplicationUserRepository applicationUserRepository;

    @Transactional
    public List<Exercise> getAllExercises() {

        Principal principal = SecurityContextHolder.getContext().getAuthentication();

        Optional<ApplicationUser> applicationUser = applicationUserRepository.findApplicationUserByUsername(principal.getName());

        List<Exercise> exercises = new ArrayList<>();
        if(applicationUser.isPresent()){
            exercises = applicationUser.get().getExercises();

            }

        return exercises;
    }
}

测试:

@SpringBootTest
@AutoConfigureMockMvc(addFilters = false)
public class ExerciseControllerTest {

    private final MockMvc mockMvc;
    private final ObjectMapper objectMapper;
    @Mock
    ApplicationUserRepository applicationUserRepository;

    @Autowired
    public ExerciseControllerTest(MockMvc mockMvc,
            ApplicationUserRepository applicationUserRepository, ObjectMapper objectMapper) {
        this.mockMvc = mockMvc;
        this.applicationUserRepository = applicationUserRepository;
        this.objectMapper = objectMapper;
    }

    @BeforeEach
    public void initMocks() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    @WithMockUser(username = "testUser")
    public void testGetExercises() throws Exception {

         Exercise ex = new Exercise();
         ex.setData("test");
         ApplicationUser user = new ApplicationUser();
         Exercise[] exercises = {ex};
         List<Exercise> list = new ArrayList<Exercise>(Arrays.asList(exercises));
         user.setExercises(list);
         Optional<ApplicationUser> userToReturnFromRepository = Optional.of(user);

        when(applicationUserRepository.findApplicationUserByUsername("testUser"))
        .thenReturn(userToReturnFromRepository);

        mockMvc.perform(get("/api/v1/exercises")).andExpect(status().isOk()).andExpect(jsonPath("$", hasSize(1)));

    }
}
hsvhsicv

hsvhsicv1#

在你的测试中有两个矛盾的事情发生:
您正在使用mockito通过反射初始化一个mock实现
applicationuserrepository通过构造函数被spring注入到测试类中。
最终的结果是:
spring将applicationuserrepository注入构造函数参数
applicationuserrepository字段在构造函数中设置为spring注入版本
mockito初始化一个新的applicationuserrepository mock
mockito用mock替换applicationuserrespository字段(即,告别mvc安装程序正在使用的springbean的句柄!)
我能想到的最简单的解决方法是使用@mockbean而不是@mock结合构造函数注入@mockbean将指示spring为您创建模拟示例,使用它,并在测试中提供给您。

@SpringBootTest
@AutoConfigureMockMvc(addFilters = false)
public class ExerciseControllerTest {

    private final MockMvc mockMvc;
    private final ObjectMapper objectMapper;
    @MockBean // User MockBean instead of Mock
    ApplicationUserRepository applicationUserRepository;

    @Autowired
    public ExerciseControllerTest(MockMvc mockMvc, ObjectMapper objectMapper) {
        this.mockMvc = mockMvc;
        //remove the applicationUserRepository injection
        this.objectMapper = objectMapper;
    }

// remove MockitoAnnotations.openMocks(this);
//...

...
}

相关问题