4

I'm unhappily dealing with an interface someone defined with the following

public Map<?, ?> getMap(String key);

I'm trying to write unit tests that consume this interface.

Map<String,String> pageMaps = new HashMap<String,String();
pageMaps.put(EmptyResultsHandler.PAGEIDENT,"boogie");
pageMaps.put(EmptyResultsHandler.BROWSEPARENTNODEID, "Chompie");
Map<?,?> stupid = (Map<?, ?>)pageMaps;
EasyMock.expect(config.getMap("sillyMap")).andReturn(stupid);

and the compiler is borking.

The method andReturn(Map<capture#5-of ?,capture#6-of ?>) in the type IExpectationSetters<Map<capture#5-of ?,capture#6-of ?>> is not applicable for the arguments (Map<capture#7-of ?,capture#8-of ?>)

If I try to use pageMaps directly, it tells me:

The method andReturn(Map<capture#5-of ?,capture#6-of ?>) in the type IExpectationSetters<Map<capture#5-of ?,capture#6-of ?>> is not applicable for the arguments (Map<String,String>)

If I make pageMaps a Map<?,?>, I can't put Strings inside of it.

The method put(capture#3-of ?, capture#4-of ?) in the type Map<capture#3-of ?,capture#4-of ?> is not applicable for the arguments (String, String)

I've seen some client code that does ugly unchecked conversions, like

@SuppressWarnings("unchecked")
        final Map<String, String> emptySearchResultsPageMaps = (Map<String, String>) conf.getMap("emptySearchResultsPage");

How do I get data into a Map<?,?>, or convert my Map<String,String> to Map<?,?> ?

4
  • There is kind of confusion here: You try to convince the compiler that stupid is a Map with 2 type arguments you don't care about, but nevertheless, you use the Map at the type Map<String, String>. But what you should do is to test that the interface works for any combination of types you need. Commented Feb 24, 2013 at 10:17
  • What happens if you make it return pageMaps? EasyMock.expect(config.getMap("sillyMap")).andReturn(pageMaps); Commented Feb 24, 2013 at 10:20
  • I only care about it as a Map<String,String> for this test, but that is irrelevant. I don't see how I can "test that the interface works for any combination of types that I need" if I cannot get data into it. If I make the map completely generic, put() refuses to work. Commented Feb 24, 2013 at 10:23
  • @JBNizet That was what I meant by "when I true to use pageMaps directly" Commented Feb 24, 2013 at 10:24

1 Answer 1

5
  1. There is no way you can write Map<String, String> map = getMap("abc"); without a cast
  2. The problem has more to do with easymock and the types returned/expected by the expect and andReturn methods, which I'm not familiar with. You could write

    Map<String, String> expected = new HashMap<String, String> ();
    Map<?, ?> actual = getMap("someKey");
    boolean ok = actual.equals(pageMaps);
    //or in a junit like syntax
    assertEquals(expected, actual);
    

Not sure if that can be mixed with your mocking stuff. This would maybe work:

EasyMock.expect((Map<String, String>) config.getMap("sillyMap")).andReturn(pageMaps);

Also note that you can't add anything to a generic collection with a wildcard. So this:

Map<?, ?> map = ...
map.put(a, b);

won't compile, unless a and b are null.

Sign up to request clarification or add additional context in comments.

1 Comment

Nicely done, I hadn't thought of trying to cast inside of the expect call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.