Unit test problem with a embedded database process

I have a problem when running the unit test (run by gradle build).
I use ru.yandex.qatools.embed:postgresql-embedded:2.4 to create a embedded postgres database in unit test. It work properly with CircleCI 1.0, but when upgrading to CircleCI 2.0, the unit test have been failed with the logs:

org.springframework.transaction.CannotCreateTransactionException
        Caused by: org.hibernate.exception.JDBCConnectionException
            Caused by: org.postgresql.util.PSQLException
                Caused by: java.net.ConnectException
    java.lang.NullPointerException at AccountControllerTest

That’s probably not enough information to help. CircleCI 2.0 is a different environment, to be sure, but I’d expect transactions to still work. May we see your config.yml?

It may be worth showing the Java unit test code too, but there’s a point when this becomes a unit test question (possibly for Stack Overflow etc) rather than a CircleCI question.

I post some codes here, please help me find out what problem is. Thank you very much.

config.yml

version: 2
jobs:
    checkout:
        docker: 
            - image: circleci/buildpack-deps:16.04-curl-browsers
        environment:
            TZ: "/usr/share/zoneinfo/Asia/Tokyo"
        steps:
            - checkout
            - persist_to_workspace:
                root: .
                paths:
                    - service/
                    - artifacts

    build-java:
        docker:
            - image: circleci/openjdk:8-jdk-node-browsers
        environment:
            TZ: "/usr/share/zoneinfo/Asia/Tokyo"
        steps:
            - attach_workspace:
                at: ./    
            - run:
                name: build iot-service
                pwd: service/iot-service
                command: ./gradlew clean build
            - run:
                name: collect test result
                command: |
                    mkdir /tmp/test-results
                    find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} /tmp/test-results/ \;
                    find . -type f -regex ".*/build/test-results/.*xml" -exec cp {} /tmp/test-results/ \;
            - store_test_results:
                path: /tmp/test-results
            - persist_to_workspace:
                root: .
                paths: 
                    - service/

    collect-artifacts:
        docker:
            - image: circleci/buildpack-deps:16.04-curl-browsers
        environment:
            TZ: "/usr/share/zoneinfo/Asia/Tokyo"
        steps:
            - attach_workspace:
                at: ./
            - run:
                name: collect artifact
                command: tar zcfp ./projectg-iot.tar.gz -T artifacts
            - store_artifacts:
                path: ./projectg-iot.tar.gz

workflows:
    version: 2
    build:
        jobs:
            - checkout
            - build-java:
                requires:
                    - checkout
            - collect-artifacts:
                requires:
                    - build-java

embedded datasource

@Configuration
@Profile(Profiles.TEST)
@AutoConfigureOrder(value = Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(DataSource.class)
@Import(ApiConfig.class)
public class TestConfig
{
	@Autowired
	private Environment m_env;

	private PostgresConfig m_dbConfig;


	@Bean(destroyMethod = "stop")
	public PostgresProcess databaseServer() throws Exception
	{
		final String host = "127.0.0.1";
		final String port = "12345";
		final String name = "postgres";
		final String username = "postgres";
		final String password = "postgres";

		m_dbConfig = new PostgresConfig(
				Version.Main.PRODUCTION,
				new AbstractPostgresConfig.Net(host, Integer.parseInt(port)),
				new AbstractPostgresConfig.Storage(name),
				new AbstractPostgresConfig.Timeout(),
				new AbstractPostgresConfig.Credentials(username, password)
		);

		m_dbConfig.getAdditionalInitDbParams().addAll(asList(
				"-E", "UTF-8",
				"--locale=en_US.UTF-8",
				"--lc-collate=en_US.UTF-8",
				"--lc-ctype=en_US.UTF-8"
		));

		final PostgresStarter<PostgresExecutable, PostgresProcess> runtime = PostgresStarter.getDefaultInstance();
		PostgresExecutable exec = runtime.prepare(m_dbConfig);
		PostgresProcess process = exec.start();

		File sqlDir = new File(getClass().getClassLoader().getResource("sql").getFile());
		File[] sqlFiles = sqlDir.listFiles();
		Arrays.sort(sqlFiles);

		for (File sqlFile : sqlFiles) {
			process.importFromFile(sqlFile);
		}

		return process;
	}
}

Unit test code

@Transactional
@ActiveProfiles(Profiles.TEST)
@RunWith(SpringRunner.class)
@SpringBootTest
public class AccountControllerTest
{
	@Autowired
	private WebApplicationContext m_appContext;

	@Autowired
	private AccountService m_accountService;

	private static final String REQUEST_URL = ApiPath.ACCOUNT_API_PATH;

	@Autowired
	private LibProperty m_libProperty;

	@Autowired
	private RestTemplate m_restTemplate;

	private MockRestServiceServer m_mockServer;

	@Autowired
	private ResourceFactory m_resourceFactory;

	@Before
	public void setUp() throws Exception
	{
		m_mockServer = MockRestServiceServer.bindTo(m_restTemplate).ignoreExpectOrder(true).build();
	}

	@After
	public void tearDown()
	{
		m_mockServer.verify();
	}

	@Test
	public void testCreateAccountReturnIsCreated() throws Exception
	{
		final String json = "{\"account\":\"" + ACCOUNT_ID + "\"}";
		ResultActions resultActions = TestUtils.perform(m_appContext, post(REQUEST_URL)
				.content(json)
				.contentType(MediaType.APPLICATION_JSON_UTF8))
				.andExpect(status().isCreated());
		assertAccountResponseBodyMatch(resultActions, ACCOUNT_ID);

		Account account = m_accountService.find(ACCOUNT_ID);
		assertNotNull(account);
	}
}

That’s certainly some useful information, but now this is “will a volunteer fix my tests for me”? The answer is probably no :smiley_cat:

However, with this information, you may find people will chip in to make suggestions of things you can try.

I have not encountered embedded Postgres before, but consider these things:

  • Does is spawn a process? PostgresExecutable makes me think it does. If so, does that process start? How can you verify that it has started?
  • Does this process produce logs? If so, do they have any failures in them?
  • Could you get a SSH on a failed build and add some debug statements into your code, to see where it is failing? Use nano to edit and apk add to install things (nano, jdk, etc).

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.