【问题标题】:JUnit test Custom exception that throws @httpStatusJUnit 测试引发@httpStatus 的自定义异常
【发布时间】:2018-02-27 19:41:00
【问题描述】:

我想测试当我调用这样的方法时是否引发了我的自定义异常:

private MyObject queryDatabase(String request, String end){
    HttpEntity myEntity = new NStringEntity(request, ContentType.APPLICATION_JSON)
    Response response = restClient.performRequest("GET", end,Collections.emptyMap(), myEntity)

    MyObject myObject = mapper.readValue(response.getEntity().getContent(), MyObject.Class);
    if(myObject.getFunctions().isEmpty()){
        throw new EmptyResultException("Empty result");
    }
    return myObject;
}

我的EmptyResultException班级:

@ResponseStatus(value=HttpStatus.NO_CONTENT)
public Class EmptyResultException() extends RuntimeException(){
    ...
}

我刚开始使用 JUnit,我已经尝试过:

@Mock MyService myservice;

@Test(expected=EmptyResultException.class)
public void shouldReturnException() {
    when(myService.queryDatabase(anyString(),anyString())).thenReturn(new MyObject());
}

它不工作。我想尝试的行为是private 方法。看来我应该在这种情况下使用 Powermock。但是,我读过测试private 方法不好,所以我想将我的方法更改为public。有什么帮助吗?

编辑:我的完整实现:​​

我有一个 Restcontroller :

@RestController
@RequestMapping...
public class MyController {

    @Autowired 
    MyService myService;

    @RequestMapping...
    public MyObject findObject(@Valid DtoParameters parameters){
      return myService.executeQuery(parameters);
   }
   }

在 myService 类中:

@Service
public class MyService{

public MyObject executeQuery(DtoParameters parameters){
 return 
    queryDatabase(parameters.buildRequest(),parameters.buildEnd());

}
}

【问题讨论】:

  • 私有方法queryDatabase() 将作为调用方法的一部分进行测试(我假设它是公共的)。您可以简单地在调用方法中验证响应。
  • 你是在测试MyService,还是在嘲笑它?你不能同时做这两件事。
  • 我正在测试我的服务在返回空对象时是否抛出异常。我做错了吗?
  • @user2004685 是的,调用方法是公开的。您能否通过简单地验证调用方法中的响应来解释更多含义?
  • @John 您能否在此处包含您的public 方法的实现?

标签: java spring junit powermockito


【解决方案1】:

如果你的测试类是MyService,它不应该有@Mock

我不知道您的整个实现,但我们假设 MyService 已注入依赖项(如您的 mapper

首先我会模拟映射器并将其注入MyService

@Mock
private ObjectMapper mapper;

@InjectMocks
private MyService myService;

为此,您的测试类需要使用 mockito 运行器。你可以用这个来注释你的类:

@RunWith(MockitoJUnitRunner.class)

模拟将被注入 MyService。 现在您可以模拟您的映射器以返回一个空对象:

when(mapper.readValue(any(),any())).thenReturn(new MyObject());
myService.queryDatabase("request", "end")

调用queryDatabase时,应该调用里面的mock。

如果您尝试测试您的休息控制器,这是一种不同的方式。我建议的是对 MyService 进行单元测试。如果您想测试控制器,您应该使用SpringRunnerSpringBootTestMockMvc。但首先,对您的服务进行单元测试,然后在您的控制器上添加其他测试。对于控制器,您可以使用 @MockBean 注释 MyService 并抛出,或者 Autowire 它和 @MockBean 内部的映射器返回一个空对象,如单元测试。

检查这个:https://spring.io/guides/gs/testing-web/


旧答案:

您可以将您的方法更改为protected,假设您的测试与您正在测试的类在同一个包中,您将能够模拟它。

要模拟你的方法,你需要这样写:

when(myService.queryDatabase(anyString(),anyString())).thenThrow(EmptyResultException.class);

您忘记使用when 方法来结束您的通话。

【讨论】:

  • 谢谢你的回复,我没明白:如果你十直接抛出 EmptyResultException ,测试总是可以的,对吗?
  • 是的,您需要完成测试。你的被测班级是MyService?如果是这种情况,您不应该在上面使用@Mock。我会更新我的答案。
  • yes Myservice 是包含 queryDatabase method() 的类。如果测试总是没问题并且总是通过,这意味着它不相关,对吧?
  • 当您使用@Mock 进行注释时,它不会创建您的真实对象。您不应该使用此注释来注释您的测试类。我用你应该做什么更新了我的答案。
  • 如果您尝试测试您的休息控制器,这是一种不同的方式。我建议的是对 MyService 进行单元测试。如果你想测试控制器,你应该用 SpringRunner SpringBootTest 和 MockMvc 来做。但首先,对您的服务进行单元测试,然后在您的控制器上添加其他测试。对于控制器,您将使用 @MockBean 注释 MyService。检查这个:spring.io/guides/gs/testing-web
猜你喜欢
  • 1970-01-01
  • 2013-11-01
  • 1970-01-01
  • 2017-08-28
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多