11

I' ve got some business logic class:

public class SomeService {
    public void doFirst() {}

    public void doSecond() {
        doFirst();
    }
}

and test for it:

public class SomeServiceTest {

    private SomeService service;

    @Before
    public void setUp() {
        service = new SomeService();
    }

    @Test
    public void doSecond_someCondition_shouldCallFirst() {

        // given
        ...

        // when
        service.doSecond();

        //then
        how to verify doFirst() was called? 
    }
}

How to verify doFirst() was called not on mock, but real service?

Rufi
  • 2,529
  • 1
  • 20
  • 41
Michał Mielec
  • 1,582
  • 1
  • 14
  • 38

2 Answers2

13

I wonder why you want to test, what method your method under tests invoke. Sounds pretty much like whitebox testing to me.

In my opinion, you want to verify the outcome of the invocation and not the way to get there, as this might easily change (i.e. when refactoring).

So if the outcome of doSecond() is the same as doFirst() you could write a test for doFirst() and use the same test (i.e. set of assertions) for testing doSecond().

But if you really want to test, whether doFirst() has been invoked by doSecond() you could wrap your service in a spy and then call the verification on the spy:

//given
SomeService service = new SomeService();
SomeService spy = Mockito.spy(service);
//when
spy.doSecond();
//then
verify(spy).doFirst();
Gerald Mücke
  • 10,724
  • 2
  • 50
  • 67
  • But sometimes you don't have the chance to new a service, the system or test framework may initial the service by StartService or BindService, you can only get the service instance. You can't spy it and then replace it. – jiaqi jiang Jun 17 '20 at 02:58
  • The test against the observable outcome of the call. What does the service do, that yields an observable result? Maybe unit tests isn't the right approach in that case, and integration test would be better. Or focus on a better testability of the solution, there are often multiple ways to solve a problem. – Gerald Mücke Jun 18 '20 at 20:59
1

It sounds like you want to avoid the real doFirst being called in your test? if so, try this...

  //given
    boolean firstCalled = false;
    SomeService fakeService  = new SomeService {
          @Override 
          public void doFirst() {
             firstCalled = true;
          }
    }
 //when
 fakeService.doSecond();

  // then
  assertTrue(firstCalled);

This testing/mocking technique is called 'subclass and override' for obvious reasons.

KarlM
  • 1,614
  • 18
  • 28