Search code examples
javajunitmocking

Mocking object in set


I have the following classes:

@Getter //lombok
@AllArgsConstructor //lombok
public class A {
    private Set<B> bSet;

    public void aMethod() {
        for (B b: bSet) b.bMethod();
    }
}

@AllArgsConstructor //lombok
public class B {
    public void bMethod() { 
        //do something
    }
}

I would like to write a test that checks if bMethod() got called for every element of bSet without caring about the Implementation of bMethod(). A unit test.

This is my JUnit test case that needs to succeed:

    @Test
    public void givenAWithBSet_whenAMethodIsCalled_thenCallBMethodOnAllBs() {
        //GIVEN a with bSet
        Set<B> bSet = new HashSet<>();
        bSet.add(new B());
        bSet.add(new B());
        
        A a = new A(bSet);

        //WHEN aMethodIsCalled
        a.aMethod();

        //then call bMethod on all bs
        bSet.forEach(b -> verify(b, times(1)).bMethod());
        bSet.forEach(Mockito::verifyNoMoreInteractions);
    }

I tried mocking it, but was unsuccessful and need your help


Solution

  • If you want to just verify that each B in your Set has its bMethod invoked, you can set up your test something like this:

    @Test
    public void givenAWithBSet_whenAMethodIsCalled_thenCallBMethodOnAllBs() {
        Set<B> bSet = new HashSet<>();
        for (int i = 0; i<10; i++) {
            bSet.add(Mockito.mock(B.class));
        }
    
        A a = new A(bSet);
    
        a.aMethod();
    
        for (B b : a.getBSet()) {
            verify(b).bMethod();
        }
    }
    

    It will verify that bMethod was called on each of the mocks. It'd be nice to use the same mock, but as you're using a Set and the mock uses the identity function for equality, you'll need to create multiples.