如何模仿feign.Client.Default与Mockito

时间:2015-10-08 01:33:11

标签: java jersey mockito dropwizard netflix-feign

我正在编写Dropwizard应用程序并使用Feign来构建对外部服务的客户端调用。我有自定义编码器和解码器,我正在注册feign.Builder,如下所示:

    this.feignBuilder = Feign.builder()
            .contract(new JAXRSContract()) // we want JAX-RS annotations
            .encoder(new JacksonEncoder()) // same as what dropwizard is using
            .decoder(new CustomDecoder())
            .errorDecoder(new CustomErrorDecoder())
            .requestInterceptor(new AuthKeyInterceptor(config.getInterceptor()));

我正在为feign客户端调用编写单元测试,因此我可以观察假装机器如何处理我的编码器/解码器覆盖和异常时的气泡。我现在对使用假服务器编写集成测试不感兴趣(这是我看到人们为这种情况编写的最常见的测试类型)。

这应该是直截了当的。我想模仿feign发出请求的点,让它返回我的假响应。这意味着我应该模拟对feign.Client.Default.execute的调用,以便在请求为this call site时返回我的假响应。这个模拟的例子如下:

String responseMessage = "{\"error\":\"bad\",\"desc\":\"blah\"}";
feign.Response feignResponse = FeignFakeResponseHelper.createFakeResponse(404,"Bad Request",responseMessage);
Client.Default mockFeignClient = mock(Client.Default.class);
try {
     when(mockFeignClient.execute(any(feign.Request.class),any(Request.Options.class))).thenReturn(feignResponse);
} catch (IOException e) {
     assertThat(true).isFalse(); // fail nicely
}

没有运气。当我在代码中到达call site请求时,Cleint.Default类不会被模拟。我做错了什么?

2 个答案:

答案 0 :(得分:0)

事实证明Mockito不足以做我认为可以做的事情。正确的解决方案是使用PowerMockito来模拟构造函数,以便Client.Default在包含该引用的类中实例化时返回模拟的实例。

经过大量的编译错误后,我得到PowerMockito进行编译,看起来好像有用了。唉它没有回复我的模拟,电话仍在通过。我过去曾尝试PowerMockito,因为它造成了额外的问题而从未使用它。所以我仍然认为只是即插即用并不容易。

很遗憾,尝试做这样的事情是如此困难。

答案 1 :(得分:0)

如前所述,Mockito不够强大。 我用手动模拟解决了这个问题。

比听起来容易:

<强> MyService.Java

public class MyService{
    //My service stuff      

    private MyFeignClient myFeignClient;

    @Inject //this will work only with constructor injection
    public MyService(MyFeignClient myFeignClient){
        this.MyFeignClient = myFeignClient
    }


    public void myMethod(){
        myFeignClient.remoteMethod(); // We want to mock this method
    }
}

<强> MyFeignClient.Java

@FeignClient("target-service")
public interface MyFeignClient{

    @RequestMapping(value = "/test" method = RequestMethod.GET)
    public void remotemethod();
}

如果您想在模仿feignclient时测试上面的代码,请执行以下操作:

<强> MyFeignClientMock.java

@Component
public class MyFeignClientMock implements MyFeignClient {

    public void remoteMethod(){
         System.out.println("Mocked remoteMethod() succesfuly");
    }
}

<强> MyServiceTest.java

@RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {

    private MyService myService;

    @Inject
    private MyFeignClientMock myFeignClientMock;

    @Before
    public void setUp(){
       this.myService = new MyService(myFeignClientMock); //inject the mock
    }

    //Do tests normally here...
}