2015-12-21 141 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(); 
    } 
}