Search code examples
unit-testingjunitmockito

Mockito: Confusion Over MockedStatic


The only thing worse than "My code doesn't work and I have no idea why" is "My code works and I have no idea why."

The test in the below code snippet only runs if mockStatic() is called in beforeAll(), despite the fact that the instance it returns is never used. (This is the crux of what's hanging me up- see comment in code below)

Based on everything I've read, we should have to do something like mockedStaticRepo.when(Repository::getInstance).thenReturn(repository) to explicitly tell Mockito to return the mocked repository.

Can someone help me understand what is going on here?

Edit: Using Mockito Core 4.8.0


    @Mock
    Application application;

    @Mock
    SomeListener listener;

    @Mock
    RepositoryInterface repository;

    // Why is this necessary, even though the instance is never used?
    static MockedStatic<Repository> mockedStaticRepo;

    ViewModel viewModel;

    @BeforeAll
    public static void beforeAll()
    {
        mockedStaticRepo = mockStatic(IdsRepository.class);
    }

    @BeforeEach
    void beforeEach()
    {
        when(Repository.getInstance(this.application)).thenReturn(repository);

        ViewModel.Factory factory =
               new ViewModel.Factory(this.application, listener);

        viewModel = spy(factory.create(ViewModel.class));
    }

    @AfterAll
    public static void afterAll()
    {
        mockedStaticRepo.close();
    }

    @Test
    void testListenerOperation()
    {
        viewModel.operation();

        verify(listener).onOperation();
    }

Solution

  • I found the extra information that made it click for me in the documentation for MockedStatic<T>.

    If the Mock annotation is used on fields or method parameters of this type, a static mock is created instead of a regular mock.

    In other words, MockStatic() isn't changing the behavior of MockitoCore::when(...).thenReturn(...). It is changing the behavior of the @Mock annotation, such that repository is a static mock within the scope that mockStatic() is called.