【问题标题】:Null when injecting mock services, testing a RestController - Mockito注入模拟服务时为空,测试 RestController - Mockito
【发布时间】:2021-01-26 20:34:06
【问题描述】:

我正在测试一个 REST 控制器,我想注入模拟服务。

但我在调用服务 Mock 时得到一个 null

这是我的代码:

界面:

interface CaseManagementService {
fun createAccount(caseRequest: CaseRequestDto): Mono<CaseResponseDto>
} 

服务:

@Service
class CaseManagementServiceImpl(private val clientManagementService: 
ClientManagementService) : CaseManagementService {

   override fun createAccount(caseRequest: CaseRequestDto): Mono<CaseResponseDto> {
    return clientManagementService.createAccount(caseRequest)
  }
}

控制器:

@RestController
@RequestMapping("somepath")
class CaseController(private val caseManagementService: CaseManagementService) {

@PostMapping()
fun createCase(@RequestBody caseRequest: CaseRequestDto): Mono<CaseResponseDto> {
    return caseManagementService.createAccount(caseRequest)    }
}

测试:

@SpringBootTest
class CaseControllerTests {
@Test
fun `createCase should return case id when a case is created`() {

    val caseManagementService: CaseManagementServiceImpl =   
    Mockito.mock(CaseManagementServiceImpl::class.java)

    val caseResponseDtoMono = Mono.just(Fakes().GetFakeCaseResponseDto())
    val requestDto = Fakes().GetFakeCaseRequestDto()

     
    `when`(caseManagementService.createAccount(requestDto).thenReturn(caseResponseDtoMono))

    var caseController = CaseController(caseManagementService)

//NULL EXCEPTION HAPPENS HERE - RETURNS NULL THIS CALL
    var result = caseController.createCase(Fakes().GetFakeCaseRequestDto())

    StepVerifier.create(result)
        .consumeNextWith { r -> assertEquals(Fakes().GetFakeCaseResponseDto().id, r.id) 
    }.verifyComplete()
  }
 } 

【问题讨论】:

    标签: spring-boot kotlin mockito spring-webflux


    【解决方案1】:

    右括号在错误的位置:您正在调用 Mono.thenReturn(在从 createAccount 返回的空 Mono 实例上)而不是 Mockito 的 thenReturn(我假设这就是您的意思):

    `when`(caseManagementService.createAccount(requestDto)).thenReturn(caseResponseDtoMono)
    

    第二个问题:您正在模拟createAccount 调用CaseRequestDto 的特定实例。在实际调用中,您使用的是不同的实例,因此参数不匹配并且模拟返回 null。尝试重用请求实例,即:

    var result = caseController.createCase(requestDto)
    

    【讨论】:

    • 谢谢@Mador。刚刚意识到从控制器调用方法时返回null服务调用,尝试验证null时发生null异常(StepVerifier)
    • 我按照您的建议修复了右括号,但服务调用仍然为空
    • 谢谢@MAfor,这就是问题所在,同一参数的两个不同实例
    【解决方案2】:

    您已经模拟了服务,但没有将模拟的服务注入到 REST 控制器中。这就是为什么你得到一个空指针。所以,caseManagementService 需要注入到 CaseController 中。下面是一个链接,您可以在其中看到注入部分。在下面的代码中,我将 caseController 变量移到上面,以便在使用之前将 caseManagementService 注入到 caseControler 中。

    @SpringBootTest
    class CaseControllerTests {
    @Test
    fun `createCase should return case id when a case is created`() {
    
        val caseManagementService: CaseManagementServiceImpl =   
        Mockito.mock(CaseManagementServiceImpl::class.java)
        var caseController = CaseController(caseManagementService)
    
        val caseResponseDtoMono = Mono.just(Fakes().GetFakeCaseResponseDto())
        val requestDto = Fakes().GetFakeCaseRequestDto()
    
         
        `when`(caseManagementService.createAccount(requestDto).thenReturn(caseResponseDtoMono))
    
       
    //NULL EXCEPTION HAPPENS HERE - RETURNS NULL THIS CALL
        var result = caseController.createCase(Fakes().GetFakeCaseRequestDto())
    
        StepVerifier.create(result)
            .consumeNextWith { r -> assertEquals(Fakes().GetFakeCaseResponseDto().id, r.id) 
        }.verifyComplete()
      }
     } 
    

    https://vmaks.github.io/other/2019/11/04/spring-boot-with-mockito-and-kotlin.html

    【讨论】:

    • 但是它是通过控制器类 CaseController(private val caseManagementService: CaseManagementService) 的构造函数注入的服务,这就是你的意思?可以举个例子吗
    • @D.B,检查我在答案中编辑的代码。将 caseController 注入部分移到代码的前面,在调用时实际使用服务之前。
    猜你喜欢
    • 2021-05-28
    • 1970-01-01
    • 2018-10-15
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多