How to mock a EntityListener function?

210 views Asked by At

I'm trying to mock one function in an EntityListener, so the real implementation is not called in my test. The code looks like the following:

@EntityListeners(myEntityListener.class)
@Entity
public class myEntity {
...
}

public class myEntityListener {
    
    public String doThis() {
         // code i want to skip/mock
         return expensiveToCompute;
    }
    
    @PrePersist
    public void myListener(myEntity e) {
         if (complexConditionToTest) e.setSomething(doThis());
    }
}

I would like to mock doThis(), but run the actual myListener() function so I can test that the complex conditioning is correct.

I tried to test using Mockito, with the following code:

public class MyEntityListenerTest {

    @Autowired
    myEntityRepository repo;
    
    @MockBean
    myEntityListener entityListener;
    
    @Test
    public void myListenerTest() throws Exception {
        String expected = "fake-text";
        Mockito.when(entityListener.doThis()).thenReturn(expected);
        
        myEntity e = new myEntity();
        myEntity stored = repo.save(e);
        assertThat(stored.getSomething()).isEqualTo(expected);
    }
}

The myEntity constructor and doThis call both have more params, removed for simplicity in the example code.

I expected that this would mock the doThis function, but it does not appear to be mocked and the actual implemention is called instead. There are no error messages.

I am guessing that MockBean is not finding an existing myEntityListener bean and instead is creating a new one (which goes unused), but I am not sure how to make the test find the correct myEntityListener.

1

There are 1 answers

0
Ateig On BEST ANSWER

I couldn't get mockito to work, so I ended up creating a static field I could change instead:

@EntityListeners(MyEntityListener.class)
@Entity
public class myEntity {
...
}

public class MyEntityListener {
    public static final testing = false;

    public String doThis() {
         if (testing) return "fake-text";
         // code i want to skip/mock
         return expensiveToCompute;
    }
    
    @PrePersist
    public void myListener(myEntity e) {
         if (complexConditionToTest) e.setSomething(doThis());
    }
}

This makes the test look like:

public class MyEntityListenerTest {

    @Autowired
    myEntityRepository repo;

    @Before
    public final void setup() {
        MyEntityListener.testing = true;
    }
    
    @Test
    public void myListenerTest() throws Exception {
        String expected = "fake-text";
        myEntity e = new myEntity();
        myEntity stored = repo.save(e);
        assertThat(stored.getSomething()).isEqualTo(expected);
    }
}

If you need the expected text to change you could probably use a string property instead of a boolean, but this was fine for my use case.