【问题标题】:Mockito Test ControllerMockito 测试控制器
【发布时间】:2016-07-03 20:24:59
【问题描述】:

这是我第一次尝试使用 Mockito。

我的控制器

@RequestMapping(value = "/add", method = RequestMethod.POST)
    @ResponseBody
    public ValidationResponse startVisitForPatient(PatientBO patientBO,Locale locale) {
        ValidationResponse res = new ValidationResponse();
        if (patientManagementService.startVisit(patientBO.getId())){
            res.setStatus(MessageStatus.SUCCESS);
            res.setValue(messageSource.getMessage("success.message", null, locale));
        }
        else{
            res.setValue(messageSource.getMessage("failed.message", null, locale));
            res.setStatus(MessageStatus.FAILED);
        }
        return res;
    }

服务

@Transactional
    public boolean startVisit(long id) {
        Patient patient = patientRepository.findOne(id);
        Set<Encounter> encounters = patient.getEncounters();
        Encounter lastEncounter = null;
        Timestamp startVisitDate = null;
        Timestamp endVisitDate = null;
        if (encounters.iterator().hasNext()){
            lastEncounter = encounters.iterator().next();
            startVisitDate = lastEncounter.getStartVisitDate();
            endVisitDate = lastEncounter.getEndVisitDate();
        }
        if (lastEncounter == null || (endVisitDate != null && endVisitDate.after(startVisitDate))){
            Encounter newEncounter = new Encounter();
            newEncounter.setCreatedBy(userService.getLoggedUserName());
            newEncounter.setCreatedDate(new Timestamp(new Date().getTime()));
            newEncounter.setModifiedBy(userService.getLoggedUserName());
            newEncounter.setModifiedDate(newEncounter.getCreatedDate());
            newEncounter.setPatient(patient);
            newEncounter.setStartVisitDate(newEncounter.getCreatedDate());
            encounters.add(newEncounter);
            return true;
        }
        else
            return false;
    }

单元测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "file:src/main/webapp/WEB-INF/root-context.xml",
        "file:src/main/webapp/WEB-INF/applicationContext.xml",
        "file:src/main/webapp/WEB-INF/securityContext.xml" })
@WebAppConfiguration
public class Testing {


    @InjectMocks
    StaffVisitManagementController staffVisitManagementController;

    @Mock
    PatientManagementService patientManagementService;

    @Mock
    View mockView;

    MockMvc mockMvc;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(staffVisitManagementController)
                .setSingleView(mockView)
                .build();
    }

    @Test
    public void testStartVisit() throws Exception {
        mockMvc.perform(post("/staff/visit/add").param("id", "1"))
                .andExpect(status().isOk()).andExpect(content().string("success"));
    }
}

测试方法确实调用了控制器。但是我无法在这一行调试服务

patientManagementService.startVisit(patientBO.getId()))

它返回的只是false

我在这里错过了什么?

【问题讨论】:

  • 您在这里使用 Mockito 的具体情况如何?我看不到任何嘲笑,所以不清楚你为什么用 Mockito 标记它。
  • 对不起,我应该发布更完整的代码。请查看更新的问题。谢谢!

标签: spring-mvc mockito


【解决方案1】:

当您使用 Mockito 模拟某些东西时,它会模拟出 一切 以返回某种默认值。对于对象,这是null。对于整数/双精度/等,这是0,对于布尔值,false。请参阅Mockito Docs。所以你不能介入它,因为它不是你的类出现在被测控制器中,它是一个生成的代理,只是假装你的类(因此,模拟)。

如果你想改变你的类的行为,你需要使用 Mockito 告诉它根据传递给方法的内容或它正在运行的测试返回不同的变量。例如

when(patientManagementService.startVisit(1)).thenReturn(true);

这意味着,如果任何使用模拟的PatientManagementService 的代码调用patientManagementService.startVisit(patientBO.getId()),其中patientBO.getId() 返回1,那么它将返回true,否则它将返回false,这是默认答案。

就您而言,我怀疑如果您希望能够进入您的服务层代码,最好模拟出patientRepository,而不是patientManagementService

编辑:

我的建议大致是:

private StaffVisitManagementController staffVisitManagementController;

private PatientManagementService patientManagementService;

@Mock
private PatientRepository patientRepository;

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
    when(patientRepository.findOne(1)).thenReturn(new Patient());
    patientManagementService = new PatientManagementService(patientRepository);
    staffVisitManagementController = new StaffVisitManagementController(patientManagementService);
    mockMvc = MockMvcBuilders.standaloneSetup(staffVisitManagementController)
            .setSingleView(mockView)
            .build();
}

显然,存储库类的名称可能不同,并且您可能使用字段注入而不是构造函数注入等,但否则这应该允许您使用调试器进入PatientManagementService。你将无法进入PatientRepository,因为那会被嘲笑。

【讨论】:

  • 感谢您的信息。你能用我的代码说明一下吗?
  • 看看编辑,我强烈建议您阅读 Mockito 文档 - 它有很多功能,超出了我在这个答案中合理涵盖的范围。
  • 当然,您的回答很有帮助。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-29
相关资源
最近更新 更多