cloud1105 / mockito

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

Mockito 1.9.5 throws NPE sometimes when parameter matches returns false. #457

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?

Here is my dao:

    @Repository
    public class DAO {
        public static final ResultSetExtractor<Boolean> EXTRACTOR =
            new ResultSetExtractor<Boolean>() {
                @Override
                public Boolean extractData(ResultSet rs) throws SQLException {
                    return rs.next();
                }
            };

        @Autowired
        private NamedParameterJdbcOperations namedParameterJdbcOperations;

        @Override
        public boolean foo(String param1, int param2) {
            SqlParameterSource namedParameters = new MapSqlParameterSource("a", param1).addValue("b", param2);
            return namedParameterJdbcOperations.query("select 1 from mytable where a = :a and b = :b", namedParameters , EXTRACTOR);
        }
    }

And here is my test:

    @RunWith(MockitoJUnitRunner.class)
    public class MyTest {
        @Mock
        private NamedParameterJdbcOperations namedParameterJdbcOperations;

        @InjectMocks
        private DAO dao;

        @Test
        public void test123() {
           Mockito.when(namedParameterJdbcOperations.query(any(String.class), any(MapSqlParameterSource.class),         any(ResultSetExtractor.class))).thenReturn(Boolean.TRUE);
            assertTrue(dao.foo("123", 1));

        }
    }

It works fine when 'any' is used.

But if I replase any with Matcher.eq, then I got NPE on dao.foo call:

    @RunWith(MockitoJUnitRunner.class)
    public class MyTest {
        @Mock
        private NamedParameterJdbcOperations namedParameterJdbcOperations;

        @InjectMocks
        private DAO dao;

        @Test
        public void test123() {
           Mockito.when(namedParameterJdbcOperations.query(eq("123"), any(MapSqlParameterSource.class),         any(ResultSetExtractor.class))).thenReturn(Boolean.TRUE);
            assertTrue(dao.foo("123", 1));

        }
    }

gives me NPE. 

What is the expected output? What do you see instead?
Not NPE.

What version of the product are you using? On what operating system?
Mockito 1.9.5.

Please provide any additional information below.
Well, finally I got a solution, I found that this happens, when in method 
matching equals returns false. But not in all cases. 
This problem is very hard to Deal with as you have only an NPE without any 
additional info. And you can only find out by guess, what's happened. Very 
frustrating.

Original issue reported on code.google.com by gousei...@gmail.com on 17 Oct 2013 at 5:57

GoogleCodeExporter commented 8 years ago
Actually this is rather a limitation of the type system of java and what 
mockito can do about.

The NPE comes from the result of the `namedParameterJdbcOperations.query(...)` 
if you look at the signature 
T query(String sql, SqlParameterSource paramSource, ResultSetExtractor rse) ``` T is erased to `Object`, and the default return value for an `Object` is `null`, which is of course raising an NPE when java tries to unwrap it to a native boolean. For such cases, you may want to actually stub a default value in the `@Before` for example : ``` @Before public void prevent_NPE_for_stubs_that_return_Object_but_expect_wrappers() { given(namedParameterJdbcOperations.query( any(String.class), any(MapSqlParameterSource.class), any(ResultSetExtractor.class)) ).thenReturn(Boolean.FALSE); } ``` So when the matchers in the actual test don't work, this stub from the setup will work. HTH ``` Original comment by `brice.du...@gmail.com` on 24 Jul 2014 at 7:44 - Changed state: **WontFix**