-1

I have a class Service that calls a method of singleton class. I would like to mock a saveContract method calls.

public class Service {
    public Contract save(Contract contract) {
        Contract result;
        ...
        result = ContractDao.getInstance().saveContract(contract);
        ...
        return result;
    }
}

I modified Service class like this (added a field and a constructor, for testing purposes only):

public class Service {
    private final ContractDao contractDao;
    
    public Service() {
        this(ContractDao.getInstance());
    }
    
    public Service(final ContractDao contractDao) {
        this.contractDao = contractDao;
    }
    
    public Contract save(Contract contract) {...}
}

And my test class is:

@ExtendWith(MockitoExtension.class)
class ServiceTest {
    @Mock
    ContractDAO contractDaoMock;
    
    private Service service;
    
    @BeforeEach
    public void setup() {
        service = new Service(contractDaoMock);
    }
    
    @Test
    void saveContractTest() {
        Contract changedContract = new Contract(...);
        when(contractDaoMock.saveContract(any())).thenReturn(changedContract);
    
        Contract givenContract = new Contract(...);
        Contract actualContract = service.save(givenContract);
    
        //Assertions
        ...
    }
}
ChrisCross
  • 23
  • 4
  • 1
    Does this answer your question? [Mocking static methods with Mockito](https://stackoverflow.com/questions/21105403/mocking-static-methods-with-mockito) – Jens May 05 '21 at 11:15
  • No. I have no reasons to use PowerMockito. I did it as described here: [Mocking a singleton with mockito](https://stackoverflow.com/questions/38914433/mocking-a-singleton-with-mockito) – ChrisCross May 05 '21 at 11:28
  • No you don't. You never mocked `ContractDao.getInstance()` – Jens May 05 '21 at 11:29
  • What do you mean? – ChrisCross May 05 '21 at 11:33
  • 1
    @ChrisCross `result = ContractDao.getInstance().saveContract(Contract contract);` is calling in your test. So you shoul change your implementation of `Service` and use initialized `ContractDAO` field or you should mock `ContractDao.getInstance()` – Alex May 05 '21 at 12:20
  • `result = ContractDao.getInstance().saveContract(Contract contract);` is calling in service and **not** in test. – ChrisCross May 05 '21 at 12:46

2 Answers2

1

Add mockito-inline dependency and use the MockedStatic to mock the getInstance() method.

Your code should look like that:

    @Test
    void saveContractTest() {
        Contract changedContract = new Contract(...);
        try (MockedStatic<ContractDAO> mockedContractDAO = mockStatic(ContractDAO.class) {
            mockedContractDAO.when(ContractDAO::getInstance).thenReturn(contractDaoMock);
            when(contractDaoMock.saveContract(any())).thenReturn(changedContract);
    
            Contract givenContract = new Contract(...);
            Contract actualContract = service.save(givenContract);
    
            //Assertions
            ...
        }
    }

Check the docs here to know a bit more about mocking static methods: https://javadoc.io/static/org.mockito/mockito-core/3.9.0/org/mockito/Mockito.html#static_mocks

Vitor Cavalcanti
  • 311
  • 3
  • 13
0

In Service.save() I have not replaced the line

result = ContractDao.getInstance().saveContract(contract);

with line

result = contractDao.saveContract(contract);

So, we need to use a field instance which we mocked and not the singleton.getInstance().

ChrisCross
  • 23
  • 4