Automatic DB Connection from Spring Boot Test [Ultimate]

已回答

HI,

we are using zonky embedded-database-spring-test to automatically start a database for our spring boot service tests:

<dependency>
    <groupId>io.zonky.test</groupId>
    <artifactId>embedded-database-spring-test</artifactId>
    <version>2.1.1</version>
    <scope>test</scope>
</dependency>

When running a test i can see the connection URL printed to the log and can manually change the connection setting to connect to this db.

i.z.t.d.l.EmbeddedDatabaseReporter: JDBC URL to connect to 'dataSource':
url='jdbc:sqlserver://localhost:49154;databaseName=cywlsplkqkij;user=sa;password=A_Str0ng_Required_Password', scope='ClientControllerTests#createClientsTest'

Is there a way that IntelliJ can automatically connect to this db (eg.: from running spring boot test conext)?

This would be quite useful for debugging to avoid searching the connection URL in the logs and updating the config for every test run.

We are using Postgres and MSSQL Server.

0

No such option. Data source configuration is in <project_folder>\.idea\dataSources.xml file, and passwords are stored in KeePass database (or native key chain, depending on OS), so you can try to create some script which will edit values...

0

I've prepared a Groovy script to LivePlugin that watches the log and updates the database settings in IntelliJ IDEA according to it.

Here are the instructions:
1. Install the LivePlugin plugin
2. In LivePlugin, create a new Groovy plugin and copy the snippet below into the newly created plugin.groovy file
3. In IntelliJ IDEA, create a new data source with the corresponding name and driver (embedded-postgres, embedded-sqlserver, ... - names and types are configurable at the beginning of the script)
4. Run the plugin and from that moment the database settings will be synchronized with the log

import com.intellij.database.psi.DbPsiFacade
import com.intellij.database.util.DbImplUtil
import com.intellij.execution.filters.ConsoleInputFilterProvider
import com.intellij.execution.filters.InputFilter
import com.intellij.execution.ui.ConsoleViewContentType as ContentType
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Pair

import java.util.regex.Matcher
import java.util.regex.Pattern

import static com.intellij.execution.filters.ConsoleInputFilterProvider.INPUT_FILTER_PROVIDERS
import static com.intellij.openapi.util.text.StringUtil.newBombedCharSequence
import static liveplugin.PluginUtil.changeGlobalVar
import static liveplugin.PluginUtil.show

// depends-on-plugin com.intellij.database

if (isIdeStartup) return

// =====================================================================================
// Customizable mappings of application's data sources to IntelliJ IDEA's database names
// =====================================================================================
def dataSourceMapping = [
        [ds: "dataSource", db: 'embedded-postgres', driver: 'postgresql'],
        [ds: "dataSource", db: 'embedded-sqlserver', driver: 'sqlserver'],
        [ds: "dataSource", db: 'embedded-mariadb', driver: 'mariadb'],
        [ds: "dataSource", db: 'embedded-mysql', driver: 'mysql'],
        [ds: "dataSource", db: 'embedded-h2', driver: 'h2']
]

Pattern pattern = Pattern.compile(".*JDBC URL to connect to '([^']+)': url='(jdbc:([^:]+):[^']+)'.*")

static CharSequence limitAndCutNewline(String text, int maxLength, milliseconds) {
    int endIndex = text.length()
    if (text.endsWith("\n")) {
        --endIndex
    }
    if (maxLength >= 0) {
        endIndex = Math.min(endIndex, maxLength)
    }
    def substring = text.substring(0, endIndex)

    if (milliseconds > 0) {
        return newBombedCharSequence(substring, milliseconds)
    }
    return substring
}

static def updateDatabase(Project project, String dbName, String jdbcUrl) {
    DbPsiFacade.getInstance(project).getDataSources()
            .collect { DbImplUtil.getMaybeLocalDataSource(it) }
            .findAll { it != null }
            .findAll { it.name == dbName }
            .findAll { it.url != jdbcUrl }
            .forEach { ds ->
                ds.url = jdbcUrl
                show("Database '" + ds.name + "' has been updated to '" + jdbcUrl + "'")
            }
}

static def databaseUpdater(Project project, Pattern pattern, List<Map<String, String>> mappings) {
    new InputFilter() {
        List<Pair<String, ContentType>> applyFilter(String consoleText, ContentType contentType) {
            if (!consoleText.contains("EmbeddedDatabaseReporter")) {
                return null
            }
            try {
                CharSequence textForMatching = limitAndCutNewline(consoleText, 500, 1000)
                Matcher matcher = pattern.matcher(textForMatching)
                
                if (matcher.matches()) {
                    def dsName = matcher.group(1)
                    def jdbcUrl = matcher.group(2)
                    def driver = matcher.group(3)

                    def mapping = mappings.find { it.get("ds") == dsName && it.get("driver") == driver }
                    if (mapping) {
                        updateDatabase(project, mapping.get("db"), jdbcUrl)
                    }
                }
            } catch (ProcessCanceledException ex) {
                show("Processing took too long for: " + consoleText)
            }
            return null
        }
    }
}

def extensionPoint = Extensions.rootArea.getExtensionPoint(INPUT_FILTER_PROVIDERS)
def inputFilterProvider = changeGlobalVar("EmbeddedDatabaseUpdater") { prevInputFilterProvider ->
    if (prevInputFilterProvider != null && extensionPoint.hasExtension(prevInputFilterProvider)) {
        extensionPoint.unregisterExtension(prevInputFilterProvider)
    }
    new ConsoleInputFilterProvider() {
        InputFilter[] getDefaultFilters(Project project) {
            [databaseUpdater(project, pattern, dataSourceMapping)]
        }
    }
}
extensionPoint.registerExtension(inputFilterProvider)
0

We've created a request for this feature to be implemented.

0

请先登录再写评论。