2015-12-21 158 views
7

我使用spring cloud的尤里卡和假装来进行一些服务之间的通信(可以说A和B)。现在,我想单元测试一个服务的服务层(A)。问题是,这个服务(A)使用假装客户端来请求其他服务的一些信息(B)。模拟一个Eureka Feign客户端进行单元测试

运行单元测试没有任何特殊的配置会抛出以下异常:java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: service-b =>,但我不希望任何服务器来运行。

我的问题是:是否有办法来嘲笑佯客户端,这样我就可以不运行尤里卡实例和服务(B)单元测试我的服务(A)?

编辑: 我结束了创建了佯客户存根。该存根被标记为主要组件,以强制spring在我的测试中实例化存根。
这是我想出的解决方案。

//the feign client 
@FeignClient("user") 
public interface UserClient { 
    UserEntity getUser(); 
} 

//the implementation i use for the tests 
@Component 
@Primary //mark as primary implementation 
public class UserClientTestImpl implements UserClient { 
    @Override public UserEntity getUser() { 
     return someKindOfUser; 
    } 
} 

回答

4

问题是......你甚至需要模拟吗?我经常看到,人们提到“模拟”是任何“不应该成为单元测试的一部分”的第一个解决方案。嘲笑是一种技巧,而不是一切的解决方案。 (见here)。

如果你仍然在你的代码的早期阶段,只是重构并用别的东西来代替取决于佯客户的具体实例。你可以使用一个接口,一个抽象类,一个特质或任何你想要的。不要依赖于对象本身,否则你必须“嘲笑它”。

public interface IWebClient { 
    public String get(...); 
    public String post(...); 
} 

的问题:但我有其他的代码,将做完全一样的(除了这将是佯的具体实例),我该怎么办呢? 那么,你可以写一个功能测试,并调用一个你可以在本地设置的web服务器实例 - 或者使用Wiremock,如Marcin Grzejszczak在其中一个答案中提到的那样。

public class FeignClientWrapper implements IWebClient { 
    private feign = something 

    public String get() { 
    feign.get(...) 
    } 

    public String post() { 
    feign.post(...) 
    } 
} 

单元测试用于测试的算法,if/else语句,循环:如何单位工作。不要编写代码来让mock变得合适 - 它必须是相反的方式:你的代码应该具有更少的依赖关系,并且只有当你需要验证行为(否则你可以使用存根或假对象)时,你应该模拟:你需要验证行为吗?你需要测试一个特定的方法在你的代码中被调用吗?或者,连续3次使用X,Y和Z调用某个特定的方法?那么,是的,嘲笑是好的。

否则,使用假的对象:你想要什么是测试只是调用/响应,也许是状态代码。你可能想要的只是测试你的代码如何对不同的输出做出反应(例如,字段“error”存在或不存在于JSON响应中),不同的状态代码(假设客户端文档是正确的:当GET时为200,201当POST等)。

+0

这是我想出了迄今为止的解决方案: 的佯接口 '@FeignClient( “用户”) 公共接口UserClient { //一些佯注释 UserEntity的getUser(); }' 我使用的测试 '@Component @Primary 公共类UserClientTestImpl实现UserClient { @覆盖 公共UserEntity的getUser(){ 回报someKindOfUser的实施; } }' 基本上它的方法你提到@Markon。 –

+0

你可能会在你的问题中发布代码?在评论中很难阅读代码:D我很高兴它有帮助。当你想测试行为时,你可以使用模拟。如果你想测试“连接”,请设置一个小型网络服务器! :P – Markon

1

如果你需要使用一个模拟,你可以使用Wiremock存根对于给定的请求的响应 - http://wiremock.org/stubbing.html。这样你就可以对发送的真实HTTP请求进行集成测试。对于单元测试,@Markon的答案非常好。

1

嘲笑假装客户端在微服务组件测试中非常有用。您想要测试一个微服务,而不必启动所有其他微服务。如果你使用Spring(看起来像你),@MockBean注释和一些Mockito代码将会完成这项工作。

@RunWith(SpringRunner.class) 
@SpringBootTest(webEnvironment = 
SpringBootTest.WebEnvironment.DEFINED_PORT) 
public class TestYourComponent { 
    @Configuration 
    @Import({YourConfiguration.class}) 
    public static class TestConfiguration { 
    } 

    @MockBean 
    private UserClient userClient; 

    @Test 
    public void someTest() 
    { 
     //... 
     mockSomeBehavior(); 
     //... 
    } 

    private void mockSomeBehavior() { 
     Mockito.doReturn(someKindOfUser).when(userClient).getUser(); 
    } 
} 
相关问题