ssacher-tgm / mockito

Automatically exported from code.google.com/p/mockito
0 stars 0 forks source link

Consider TypeLiteral<> for creating mocks #137

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Currently generating a generic class requires a warning suppression and a cast:

    @SuppressWarnings("unchecked")
    List<String> list = (List<String>)mock(List.class);

Given that I use a lot of generics, I dislike doing this pattern over and over. 
 The attached patch 
permits the following more "concise" approach:

    List<String> list = mock(new TypeLiteral<List<String>>() {});
    Map<String, Object> map = mock(new TypeLiteral<Map<String, Object>>() {});

Original issue reported on code.google.com by mahm...@notnoop.com on 28 Oct 2009 at 5:25

Attachments:

GoogleCodeExporter commented 8 years ago
Hi, 

thanks for the patch but I'm a bit hesitant to make it a part of the API. The 
problem
is that introduces loads of new 'mock' methods. Also I can suppress warnings on 
the
entire class and it makes the option #1 better (samller & easier to read).
Suppressing type checks warnings in tests is OK imho.

I will run your idea through other contributors - let's see what they say.

Thanks!
Szczepan

Original comment by szcze...@gmail.com on 28 Oct 2009 at 6:02

GoogleCodeExporter commented 8 years ago
Issue 135 has been merged into this issue.

Original comment by szcze...@gmail.com on 28 Oct 2009 at 6:03

GoogleCodeExporter commented 8 years ago
Issue 136 has been merged into this issue.

Original comment by szcze...@gmail.com on 28 Oct 2009 at 6:03

GoogleCodeExporter commented 8 years ago
Sounds reasonable.  I have those methods as utilities classes in my project, 
and I thought to sending them to 
you.  Personally, I like staying away from raw types as much as possible.

P.S. Didn't realize that I created so many bug reports.  Don't know how that 
happened.  Sorry!

Original comment by mit.mahm...@gmail.com on 28 Oct 2009 at 6:08

GoogleCodeExporter commented 8 years ago
This reminds me of Guice's TypeLiteral class, which services a greater 
functional
purpose than we have here, but generally I like the TypeLiteral concept.

Original comment by jhalter...@gmail.com on 28 Oct 2009 at 8:33

GoogleCodeExporter commented 8 years ago

Original comment by szcze...@gmail.com on 11 Nov 2009 at 9:06

GoogleCodeExporter commented 8 years ago
Hi,

Happy New Year :) Here are my thoughts on the subject:

1. We're not entirely comfortable doubling the number of overloaded mock() 
methods as
it makes the api bigger. The only thing I can suggest is implementing it via
'mockSettings'. For example: 

mock = mock(List.class, withSettings().genericType(new Type<List<String>>()));

What do you think?

2. Most of the devs simply suppress warnings in tests and I think it's ok given 
the
rationale behind those warnings. They try to protect your code from unexpected
ClassCastExceptions. This sort of protection might (?) be useful for production 
code
(although decently unit tested code pretty much deprecates those warnings). 
However
the usefulness for tests is questionable. Failing test can be fixed in no time 
during
development. Plus failure due to CCE around generics is very rare (I don't 
remember
ever bumping on it but my memory is short :).

Original comment by szcze...@gmail.com on 21 Jan 2010 at 10:23

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
1. I might be missing something but how can you get the correct return type with
withSettings()? E.g. I don't think it will look like this

<T> T mock(Class c,Settings<T> settings) beside withSettings is somewhat 
redundant
i.e. first you tell the Class then you tell the Class and Generics.

I don't think you should be afraid of doubling the number of methods since
conceptually they will not be doubled. e.g.

mock(List.class);
mock(new TypeLiteral<List<Foo>>(){});

to me mock method feels like one. Go with class, if generics are used go with
TypeLiteral. Simple and to the point. There are a couple of corner cases what 
to do
with mock(new TypeLiteral<? extends Foo>(){}) it doesn't make any sense.

2. I agree with your reasoning but imho the point here is minimizing visual 
noise
i.e. unnecessary warnings and explicit casts are visual noise.

Overall it is a joy to write mocks with mockito. I really like using @Mock it 
is a
non issue with Generics to use @Mock. It just works.

Original comment by alen_vre...@yahoo.com on 27 Jan 2010 at 9:59

GoogleCodeExporter commented 8 years ago
Silly me new TypeLiteral<? extends Foo>(){} is not possible to do. But you can 
do new
TypeLiteral<Foo<? extends Bar>>(){}. Eh, generics ;)

Imho it should be possible to implement this functionality like

public <T> T mock(TypeLiteral<T> literal){
   return mock(literal.getRawType());
}

Original comment by alen_vre...@yahoo.com on 28 Jan 2010 at 7:47

GoogleCodeExporter commented 8 years ago
After some brief thinking I am no longer convinced TypeLiteral is such a good 
idea in
this case.

The visual noise of 
AsyncCallback<Foo> foo = mock(new TypeLiteral<AsyncCallback<Foo>>(){});
vs
AsyncCallback<Foo> foo = unicast(mock(AsyncCallback.class));
or dare I write
AsyncCallback<Foo> foo = umock(AsyncCallback.class));

imho the non-TypeLiteral versions have less visual noise.

Original comment by alen_vre...@yahoo.com on 7 Feb 2010 at 6:54

GoogleCodeExporter commented 8 years ago
I agree. Interesting idea with the unicast/umock.

Original comment by szcze...@gmail.com on 10 Feb 2010 at 1:09

GoogleCodeExporter commented 8 years ago
Issue 161 has been merged into this issue.

Original comment by szcze...@gmail.com on 14 Feb 2010 at 12:37

GoogleCodeExporter commented 8 years ago

Original comment by szcze...@gmail.com on 14 Feb 2010 at 9:58

GoogleCodeExporter commented 8 years ago

Original comment by szcze...@gmail.com on 14 Feb 2010 at 9:58

GoogleCodeExporter commented 8 years ago
Like szczepiq, I like the unicast() / umock() methods, and it doesnt require 
much 
code at all.

Original comment by brice.du...@gmail.com on 2 Mar 2010 at 2:37

GoogleCodeExporter commented 8 years ago
Guys, can someone paste the body of unicast / umock methods? I might want to 
put it
in the docs.

Original comment by szcze...@gmail.com on 2 Mar 2010 at 9:05

GoogleCodeExporter commented 8 years ago
I think the cast method would be something like:

    @SuppressWarnings("unchecked")
    static <T> T cast(Object a) {
        return (T)a;
    }

Java's type inference would infer the proper return type when used in 
assignment 
expression (e.g. `var = cast(expr)`) but not when used in method invocation 
(e.g. 
`method(cast(expr))`).

I personally find it better to use @SuppressWarnings("unchecked") on the test 
class.  
Apparently it doesn't need an explicit cast after all:

    @SuppressWarnings("unchecked")
    void method() {
        List<String> l = mock(List.class);
        ...
    }

In practice, I found it to be the most concise approach.

Original comment by notn...@gmail.com on 2 Mar 2010 at 9:16

GoogleCodeExporter commented 8 years ago
It seems like similar functionality would be beneficial for ArgumentCaptors too.

Original comment by brianmat...@gmail.com on 11 Mar 2010 at 8:05

GoogleCodeExporter commented 8 years ago
I was thinking about this today and realized that loosening up mock()'s 
signature is
one way of solving this "problem":

static <T> T mock(Class<T> classToMock)

becomes:

static <T> T mock(Class<?> classToMock)

In the latter approach T is inferred from the return type, which can be fully
parameterized without generating a warning.

Original comment by jhalter...@gmail.com on 12 Apr 2010 at 3:50

GoogleCodeExporter commented 8 years ago
Issue 204 has been merged into this issue.

Original comment by szcze...@gmail.com on 13 Aug 2010 at 2:32

GoogleCodeExporter commented 8 years ago
@jhalterman - you are right - we discussed this idea in issue 204

Original comment by szcze...@gmail.com on 13 Aug 2010 at 2:33

GoogleCodeExporter commented 8 years ago
Just for information, I wanted to know a bit more about JSon serialisation, and 
read the JackSon documentation. And are actually using the "TypeLiteral" trick.

ObjectMapper mapper = new ObjectMapper();
Map<String,User> result = mapper.readValue(src, new 
TypeReference<Map<String,User>>() { });
In this example they create a local class, I'm not sure why they did that.

http://jackson.codehaus.org/

Original comment by brice.du...@gmail.com on 18 Aug 2010 at 8:38

GoogleCodeExporter commented 8 years ago
Just thought I'd mention it since no one else has yet:
Another advantage of supporting TypeLiteral is that you could make 
Mockito.RETURN_DEEP_MOCKS support generics.

Original comment by kristofer.karlsson@gmail.com on 11 Nov 2010 at 2:36

GoogleCodeExporter commented 8 years ago
>Another advantage of supporting TypeLiteral is that you could make 
Mockito.RETURN_DEEP_MOCKS support generics.

Can you show us an example?

Original comment by szcze...@gmail.com on 11 Nov 2010 at 2:42

GoogleCodeExporter commented 8 years ago
Here is an example of how it could work:
    @Test
    public void testTypeLiteralDeepMock() {
        List<Set> mock = Mockito.mock(new TypeLiteral<List<Set>>() {}, Mockito.RETURNS_DEEP_STUBS);
        Set mock2 = mock.get(0);
    }

Original comment by kristofer.karlsson@gmail.com on 11 Nov 2010 at 2:45

GoogleCodeExporter commented 8 years ago
Any latest best practices for this issue.  Specifically with ArgumentCaptor.

Original comment by dustin.c...@gmail.com on 3 Feb 2014 at 6:39

GoogleCodeExporter commented 8 years ago
Hi, 
I am new to Mockito, I have a code where I need to mock 

String str= "test";
ObjectMapper mapper = new ObjectMapper();
Map<String,User> result = mapper.readValue(str, new 
TypeReference<Map<String,User>>() { });

I tried to mock it with simple Mockito.mock and with Mockito.when, but was 
getting error.
Can anyone please post some example with the help of which we can mock above 
scenario.

Original comment by umesh2...@gmail.com on 3 May 2014 at 7:22

GoogleCodeExporter commented 8 years ago
@umesh please use the mailing list for this kind of support.

@Dustin Nope

Cheers,
brice

Original comment by brice.du...@gmail.com on 27 Jun 2014 at 4:44

GoogleCodeExporter commented 8 years ago
This silences the warning in Java 7:
private static <T, R extends T> T umock(Class<R> rawClass) {
  return Mockito.mock(rawClass);
}

In Java 6 it has no effect.

Original comment by ejona@google.com on 23 Oct 2014 at 11:20