2

I am making a unit test for class in my app, it just a simple class and I thought i did everything right but the test failed saying

Wanted but not invoked: mContextWeakReference.get(); -> at rahmat.com.app.utility.backwardcompatibility.StringResourceUtilTest.getString(StringResourceUtilTest.java:40) Actually, there were zero interactions with this mock.

this is the class to be tested

public class StringResourceUtil {

private static StringResourceUtil sInstance;

private WeakReference<Context> mContextWeakReference;

public static StringResourceUtil getInstance() {
    return sInstance;
}

@Inject
public StringResourceUtil(Context context) {
    mContextWeakReference = new WeakReference<>(context);
    sInstance = this;   //NOSONAR
}

public String getString(int resId) {
    return mContextWeakReference.get().getString(resId);
}}

this is unit test I made

public class StringResourceUtilTest {


private StringResourceUtil mResourceUtil;

@Mock
private Context mContext;

@Mock
private WeakReference<Context> mContextWeakReference;

@Before
public void setUp(){
    MockitoAnnotations.initMocks(this);
    mResourceUtil = new StringResourceUtil(mContext);
}


@Test
public void getString() {
    int resId = 123;
    mResourceUtil.getString(resId);
    verify(mContextWeakReference).get().getString(eq(resId));
}}

any help would be much appreciated, thanks

mangkool
  • 316
  • 2
  • 18

2 Answers2

1

Your StringUtil class is always creating a new object of mContextWeakReference object and even if you are making it, it won't inject automatically ( for that you use injectMock but no use here, since new object creation always happens internally).

public class StringResourceUtilTest {


    private StringResourceUtil mResourceUtil;

    @Mock
    private Context mContext;

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
        mResourceUtil = new StringResourceUtil(mContext);
        // setup mock return type
        // mock objects are not real,so need to moeck the behavior of method as well
        when(mContext.getString(R.string.a123)).thenReturn("123");
    }


    @Test
    public void getString() {
        int resId = R.string.a123;
        // check the return type
        assertEquals("123",mResourceUtil.getString(resId));
    }
}

Note: To verify the internal working, read

What is the difference between mocking and spying when using Mockito?

Pavneet_Singh
  • 36,884
  • 5
  • 53
  • 68
  • thank you for your answer, I followed the link you provided but still dont quite understand, so I cannot verify mContextWeakReference that it called getString() mehod ? – mangkool Aug 10 '18 at 06:14
  • @mangkool it's very simple, the test I provided is verifying the output of the code mean your desired functionality is executed hence we got the result and the behaviour you want is only applicable when we have condition to test branches and its private member so no need to test it in this specific case – Pavneet_Singh Aug 10 '18 at 16:25
0

Because you creating mContextWeakReference = new WeakReference<>(context); in constructor, it will never been a mock in StringResourceUtil.

You can set prepared mock mContextWeakReference by using

org.springframework.test.util.ReflectionTestUtils.setField(mResourceUtil , "mContextWeakReference", mContextWeakReference); 

Otherwise you should modifying StringResourceUtil class to be a testable

borino
  • 1,720
  • 1
  • 16
  • 24
  • thanks for your answer, any suggestion to make the StringResourceUtil to be testable? I tried to follow your suggestion but it is an android app and springframework is not on my dependency – mangkool Aug 10 '18 at 04:47