2017-04-07 19 views
2

tl; dr:這些測試不編譯,因爲類型參數不匹配。我應該做些什麼改變才能使它們正確編譯並運行 ?Mockito,argThat和hasEntry

https://github.com/wesleym/matchertest

我有一些在調用服務非測試代碼。它使用map參數調用服務的activate方法。

public class Foo { 
    private final Service service; 

    public Foo(Service service) { 
    this.service = service; 
    } 

    public void bar() { 
    Map<String, ?> params = getParams(); 
    service.activate(params); 
    } 

    private Map<String, ?> getParams() { 
    // something interesting goes here 
    } 
} 

一些代碼,我想測試有這樣一個服務的依賴:

public interface Service { 
    public void activate(Map<String, ?> params); 
} 

我想通過與嘲諷說的Mockito激活服務和驗證,以測試該代碼被稱爲一個合理的地圖。下面的代碼工作:

@Test 
public void testExactMap() { 
    Service mockService = mock(Service.class); 
    Foo foo = new Foo(mockService); 

    foo.bar(); 

    Map<String, String> expectedParams = new HashMap<>(); 
    expectedParams.put("paramName", "paramValue"); 
    verify(service).activate(expectedParams); 
} 

但是,我想測試,該地圖包含一個特定的條目。該Hamcrest hasEntry matcher似乎爲這個完美的使用案例:

@Test 
public void testHasEntry() { 
    Service mockService = mock(Service.class); 
    Foo foo = new Foo(mockService); 

    foo.bar(); 

    verify(mockService).activate(argThat(hasEntry("paramName", "paramValue"))); 
} 

當我嘗試這一點,我得到的IntelliJ IDEA以下錯誤:

Error:(31, 45) java: incompatible types: inference variable T has incompatible bounds 
    equality constraints: java.util.Map<? extends java.lang.String,? extends java.lang.String> 
    upper bounds: java.util.Map<java.lang.String,?>,java.lang.Object 

這裏的問題是,我需要的Map<String, ?>一個的Mockito匹配,但hasEntry給了我一個Map<? extends String, ? extends String>的匹配器。即使有明確的類型參數,我也無法弄清楚如何協調類型參數的「擴展」部分。我該怎麼做才能解決這個錯誤?是否有我應該使用的特定的強制類型或顯式類型參數?

據我所知,我可以使用ArgumentCaptor。這真的是唯一的方法嗎? Hamcrest匹配器可以嗎?

回答

3

返回類型argThat由於某種原因未被推斷。嘗試明確鑄造,如下圖所示:

Mockito.verify(foo).bar((Map<String, String>) argThat(Matchers.hasEntry("paramName", "paramValue"))); 

testHasEntryCast()可以是固定的,如下圖所示。請注意,投(Map<String, ?>)argThat返回類型:

@Test 
public void testHasEntryCast() { 
    Service mockService = mock(Service.class); 
    Foo foo = new Foo(mockService); 

    foo.bar(); 

    verify(mockService).activate((Map<String, ?>) argThat(hasEntry("paramName", "paramValue"))); 
} 
+0

首先,我有錯誤的代碼片斷了。抱歉!現在更正。其次,這是行不通的。 Service.activate預計'Map ',但在演員中不允許使用通配符。用'Object'替換'?'也不起作用。 – Wesley

+0

你能分享包括進口的測試代碼嗎? – VinPro

+0

我已經在示例項目中添加了一個指向該問題的鏈接。 – Wesley