Search code examples
springspring-boot

WebMvcTest and entitMangerFactory missing reference


I use spring boot 3

I try to do a test from the controller

userManager.findByUa

call a repository

Test

@ExtendWith(SpringExtension.class)
@WebMvcTest(value = UserController.class)
public class UserConnectionControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserManager userManager;

    @Test
    public void retrieveUserConnection() throws Exception{

        UserConnection mockUserConnection = new UserConnection(158791, "Paul Smith", "1123977", "01");

mockUserConnection.setDisabled(false);

        String expected = """
        {
            "userId": 158791,
                "name": "Paul Smith",
                "userAccess": "1123977",
                "userType": "01",
                "disabled": false
        }
        """;

        Mockito.when(userManager.findByUa(Mockito.anyString())).thenReturn(mockUserConnection);

        RequestBuilder requestBuilder = MockMvcRequestBuilders.get(
                "/users/1123977").accept(
                MediaType.APPLICATION_JSON);

        MvcResult result = mockMvc.perform(requestBuilder).andReturn();


        JSONAssert.assertEquals(expected, result.getResponse()
                .getContentAsString(), false);

    }

}

When i run this test, i get this error

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaSharedEM_entityManagerFactory': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument

Main class

@SpringBootApplication(
        scanBasePackages = { "com.acme.extranet", "com.acme.common" }
)
@EntityScan("com.acme.common")
@EnableJpaRepositories(basePackages = "com.acme.common")
public class ExtranetApplication {

    public static void main(String[] args) {
        SpringApplication.run(ExtranetApplication.class, args);
    }

}

My entity and repository and in the common package who is a jar library use in the Extranet application


Solution

  • I don't know that your context and test strategy, so it is not an accurate hint. I think there are two options.

    1. Without @MockBean

    If you just want to use UserManager as test double, just make mock object by Mockito's static method. Remove dependencies of JPA for test.

    package action.in.blog;
    
    import org.junit.jupiter.api.Test;
    import org.mockito.Mockito;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
    import org.springframework.test.web.servlet.MockMvc;
    
    import java.util.List;
    
    import static org.hamcrest.MatcherAssert.assertThat;
    import static org.hamcrest.Matchers.equalTo;
    import static org.mockito.Mockito.when;
    
    @WebMvcTest(value = UserController.class)
    public class TempTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        private UserManager userManager;
    
        @Test
        void test() {
            userManager = Mockito.mock(UserManager.class);
            when(userManager.findAll()).thenReturn(
                    List.of(new User(111))
            );
    
    
            List<User> result = userManager.findAll();
    
    
            assertThat(mockMvc != null, equalTo(true));
            assertThat(result.get(0).getId(), equalTo(111L));
        }
    }
    

    2. Using @SpringBooTest

    @WebMvcTest annotation provide minimal context for MVC test. So that cannot use JPA functionalities. And You need to append two annotations.

    • @AutoConfigureMockMvc for MockMvc injection.
    • @Transational for rollback transaction after test.
    package action.in.blog;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.List;
    
    import static org.hamcrest.MatcherAssert.assertThat;
    import static org.hamcrest.Matchers.equalTo;
    import static org.mockito.Mockito.when;
    
    @AutoConfigureMockMvc
    @Transactional
    @SpringBootTest
    public class TempSecondTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        @MockBean
        private UserManager userManager;
    
        @Test
        void test() {
            when(userManager.findAll()).thenReturn(
                    List.of(new User(111))
            );
    
    
            List<User> result = userManager.findAll();
    
    
            assertThat(mockMvc != null, equalTo(true));
            assertThat(result.get(0).getId(), equalTo(111L));
        }
    }