我正在编写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
类不会被模拟。我做错了什么?
答案 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...
}