如何模拟与数据库的连接

How to mock connection to DB

我有简单的 rest controller 测试,它在 postgresql 运行 时有效。我尝试 运行 测试,但在我停止服务 postgresql 之前,然后我的测试失败了。我如何模拟连接到数据库?我在测试中不使用数据库。

 @SpringBootTest 
    @AutoConfigureMockMvc
    public class UserControllerTest {
        @Autowired
        private MockMvc mockMvc;
        @MockBean
        private UserService service;
        @WithMockUser(username = "TestUser", roles = {"SUPER_ADMIN"})
        @Test
        public void testGetUserWhenUserIsAuthorized() throws Exception {
            UserAllInfo userAllInfo = new UserAllInfo(1L, 1L, "sdfsdf@gmail.com", "USER",
                    "userenko", Collections.singletonList(1));
            doReturn(Optional.of(userAllInfo)).when(service).getUser(1);
            mockMvc.perform(get("/api/identity/user/{id}", 1L))
                    .andDo(print())
                    .andExpect(status().isOk())
                    .andExpect(jsonPath("$.userId", is(1)))
                    .andExpect(jsonPath("$.vendingBranchId", is(1)))
                    .andExpect(jsonPath("$.email", is("sdfsdf@gmail.com")))
                    .andExpect(jsonPath("$.name", is("USER")))
                    .andExpect(jsonPath("$.surname", is("userenko")))
                    .andExpect(jsonPath("$.roles", is(Collections.singletonList(1))));
        }
  @Test
    public void testGetUserWhenUserIsUnauthorized() throws Exception {
        mockMvc.perform(get("/api/identity/user/{id}", 1L))
                .andDo(print())
                .andExpect(status().isUnauthorized());
    }
    }

我有例外列表。我认为这是两个解决方案,第一个是在内存中创建数据库,第二个是在我不使用数据库时模拟连接到数据库,但我不知道我该怎么做。

18:00:57.542 INFO  [    task-1] org.hibernate.Version                    - HHH000412: Hibernate Core {5.2.17.Final}
18:00:57.544 INFO  [    task-1] org.hibernate.cfg.Environment            - HHH000206: hibernate.properties not found
18:00:57.609 INFO  [    task-1] o.h.annotations.common.Version           - HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
18:00:57.757 WARN  [      main] o.s.b.a.o.j.JpaBaseConfiguration$JpaWebConfiguration - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
18:00:57.771 INFO  [    task-1] com.zaxxer.hikari.HikariDataSource       - HikariPool-1 - Starting...
18:00:58.739 INFO  [      main] c.e.identity.rabbit.FanoutSender         - Sending startup notification...
18:00:58.741 INFO  [      main] o.s.a.r.c.CachingConnectionFactory       - Attempting to connect to: [168.119.176.120:30672]
18:00:58.817 ERROR [    task-1] com.zaxxer.hikari.pool.HikariPool        - HikariPool-1 - Exception during pool initialization.
org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:303)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:225)
    at org.postgresql.Driver.makeConnection(Driver.java:465)
    at org.postgresql.Driver.connect(Driver.java:264)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477)
    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:560)
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115)
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:259)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:233)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:210)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:242)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:210)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:861)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:888)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.ConnectException: Connection refused (Connection refused)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:607)
    at org.postgresql.core.PGStream.createSocket(PGStream.java:231)
    at org.postgresql.core.PGStream.<init>(PGStream.java:95)
    at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:98)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:213)
    ... 34 common frames omitted
18:00:58.818 WARN  [    task-1] o.h.e.j.e.i.JdbcEnvironmentInitiator     - HHH000342: Could not obtain connection to query metadata : Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
18:00:58.836 INFO  [    task-1] org.hibernate.dialect.Dialect            - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
18:00:58.858 INFO  [    task-1] o.h.e.j.e.i.LobCreatorBuilderImpl        - HHH000422: Disabling contextual LOB creation as connection was null
18:00:58.861 INFO  [    task-1] org.hibernate.type.BasicTypeRegistry     - HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@569533c9
18:00:59.036 INFO  [      main] o.s.a.r.c.CachingConnectionFactory       - Created new connection: rabbitConnectionFactory#33eb0d4:0/SimpleConnection@19cdc217 [delegate=amqp://rabbit@168.119.176.120:30672/, localPort= 44962]
18:00:59.597 INFO  [    task-1] com.zaxxer.hikari.HikariDataSource       - HikariPool-1 - Starting...
18:01:00.599 ERROR [    task-1] com.zaxxer.hikari.pool.HikariPool        - HikariPool-1 - Exception during pool initialization.
org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:303)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:225)
    at org.postgresql.Driver.makeConnection(Driver.java:465)
    at org.postgresql.Driver.connect(Driver.java:264)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477)
    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:560)
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115)
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180)
    at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:43)
    at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:60)
    at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:40)
    at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:65)
    at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:59)
    at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:132)
    at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:96)
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:183)
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:312)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:462)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.ConnectException: Connection refused (Connection refused)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:607)
    at org.postgresql.core.PGStream.createSocket(PGStream.java:231)
    at org.postgresql.core.PGStream.<init>(PGStream.java:95)
    at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:98)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:213)
    ... 32 common frames omitted
18:01:00.602 WARN  [    task-1] o.h.e.jdbc.spi.SqlExceptionHelper        - SQL Error: 0, SQLState: 08001
18:01:00.602 ERROR [    task-1] o.h.e.jdbc.spi.SqlExceptionHelper        - Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
18:01:00.609 WARN  [      main] o.s.w.c.s.GenericWebApplicationContext   - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fanoutReceiverFromVendingDeviceService' defined in file [/home/dev/IdeaProjects/dms-identity-service/target/classes/com/ecosoft/identity/rabbit/FanoutReceiverFromVendingDeviceService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fanoutSender': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository' defined in com.ecosoft.identity.repository.UserRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
18:01:00.826 INFO  [      main] o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default'
18:01:00.826 WARN  [      main] o.s.b.f.s.DisposableBeanAdapter          - Invocation of destroy method failed on bean with name 'entityManagerFactory': javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution

更新

@AutoConfigureMockMvc
@WebMvcTest(UserController.class)
@ComponentScan("com.ecosoft.identity")
class UserController1Test {
    private String USER_NOT_EXISTS="User not exist";
    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private UserService service;
    @MockBean
    private UserDetailsServiceImpl userDetailsService;
    @MockBean
    private AuthEntryPointJwt authEntryPointJwt;
    @MockBean
    private VendingBranchRepository vendingBranchRepository;
    @MockBean
    private FanoutSender fanoutSender;

    @WithMockUser(username = "TestUser", roles = {"SUPER_ADMIN"})
    @Test
    public void testGetUserWhenUserIsAuthorized() throws Exception {
        UserAllInfo userAllInfo = new UserAllInfo(1L, 1L, "sdfsdf@gmail.com", "USER",
                "userenko", Collections.singletonList(1));
        doReturn(userAllInfo).when(service).getUser(1);
        mockMvc.perform(get("/api/identity/user/{id}", 1L))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.userId", is(1)))
                .andExpect(jsonPath("$.vendingBranchId", is(1)))
                .andExpect(jsonPath("$.email", is("sdfsdf@gmail.com")))
                .andExpect(jsonPath("$.name", is("USER")))
                .andExpect(jsonPath("$.surname", is("userenko")))
                .andExpect(jsonPath("$.roles", is(Collections.singletonList(1))));
    }


@Test
    public void testGetUserWhenUserIsUnauthorized() throws Exception {
        mockMvc.perform(get("/api/identity/user/{id}", 1L))
                .andDo(print())
                .andExpect(status().isUnauthorized());
    }
    }

但是我的测试 testGetUserWhenUserIsUnauthorized 不起作用,我得到状态 200,但我需要得到 401

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(initializers = {MyExample.Initializer.class})
@AutoConfigureMockMvc
public class MyExample {

    @BeforeClass
    public static void setTest() {
        postgreSQLContainer.start();
    }

    @ClassRule
    public static PostgreSQLContainer postgreSQLContainer =
            new PostgreSQLContainer("postgres:11.1")
                    .withDatabaseName("world-db")
                    .withUsername("world")
                    .withPassword("world123");

    static class Initializer
            implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
            // setup (postgreSQLContainer.getJdbcUrl()) as "hibernate.connection.url" here...
        }
    }

    @Test
    public void test() {
        // should be able to connect to your database here
    }
}

如果您想进行适当的集成测试,@k-wasilewski 提供的答案很棒。

如果您的目标是简单地测试应用程序的 Web 层而不需要配置数据库连接,您可以使用 @WebMvcTest(UserController.class) 注释而不是 @SpringBootTest 注释(见问题下方的评论)。 这将只创建指定控制器所需的 bean。您可能需要使用 @MockBean.

模拟某些服务和其他依赖项