#Parallel tests with Spring / Junit + Mock server + Simple Discovery Client

1 messages · Page 1 of 1 (latest)

south flintBOT
#

<@&1004656351647117403> please have a look, thanks.

jovial copper
#

Ill just paste it here for you

#

OPs original question

I have a service written in Spring with Eureka which have a lot of tests so I'm trying to run the tests in parallel.

Assuming non-parallel tests, I use mockserver-spring-test-listener-no-dependencies. I also configure my Simple Eureka client to the host and port of the Mock Server instance:

spring:
  cloud:
    discovery:
      client:
        simple:
          instances:
            service-a:
              - host: localhost
                port: ${mockServerPort}

And my test class would like something like this:

@MockServerTest
@AutoConfigureMockMvc
@SpringBootTest(classes = Application.class)
public class MyTest {
    @Autowired
    private MockMvc mockMvc;
    
    private MockServerClient client;

    @Test
    public void testA() {
        // Test
    }

    @TestB
    public void testB() {
        // Test
    }
}

Now I want to add parallelism, this can be done easily by adding a junit config file with parallelism configuration and placing @Execution(ExecutionMode.CONCURRENT) above my test class.

The problem is my tests can't be run with parallelism the way I wrote my tests because both tests try to create a MockServerClient with the same port. One of the tests will pass, the other will get an error like Exception while binding MockServer to port 49363.

I can try switching to a different test dependency like mockserver-junit-jupiter-no-dependencies which allows me to inject an instance of MockServerClient to each test (which I assume isn't shared), but now I can't inject ${mockServerPort} in my application.yml since this dependency isn't made for Spring.

Does anyone have any idea on what I can do? Maybe I'm tackling this problem in the wrong way? For context, I'm following the docs shown here: https://www.mock-server.com/mock_server/running_mock_server.html#spring_test_exec_listener

white root
#

i think ill just try to remake a new post so it isnt wonky

#

without the link

hollow badge
white root
#

alrighty

hollow badge
#

The problem is my tests can't be run with parallelism the way I wrote my tests because both tests try to create a MockServerClient with the same port. One of the tests will pass, the other will get an error like Exception while binding MockServer to port 49363.

#

The idea is that you'll start the mock server inside your test and use @DynamicPropertySource to dynamically set the port to 0 which in return will bind the server to any available port

#

Then in each of your tests you'll need to start the mock server yourself

#

but that guide doesn't cover the annotation but it shows how to create a mock server

white root
#

i see, if i tried setting it in my application-test.yml to 0 then because of the race condition theres a chance theyd both bind go the same port so it'd be better to do it in @DynamicPropertySource?

and to start the mock server for each test then I autowire the discovery client and get the port of the service?

hollow badge
#

yeah on the right track - let me write some psudoish code, sec

#
@AutoConfigureMockMvc
@SpringBootTest(classes = Application.class)
class MyTest{

  private static ClientAndServer mockServer;

  @DynamicPropertySource 
  static void dynamicProperties(DynamicPropertyRegistry registry) { 
    mockServer = ClientAndServer.startClientAndServer(0);
    registry.add("server.port",  () -> mockServer.getLocalPort()); // this might need to the path to your discovery e.g. spring.cloud.discovery.client... port
  }

  @AfterAll
  static void stop() {
    mockServer.stop();
  }

  @Autowired MockMvc mvc;


  @Test
  void testA() {
    // mockServer.when(...), mvc.perform(...)
  }
}
#

sorry bad formatting

white root
#

no worries i understood it even before you fixed it haha

#

i still have some questions but i think itd be better for me to try it out and test it for myself before that

#

thanks for the help!

hollow badge
#

if you get some concurrency issues

#

try adding @TestInstance(Lifecycle.PER_CLASS) to the top of the test

#

and if you want each test method running in parallel @Execution(ExecutionMode.CONCURRENT)

#

these are junit annotations

#

Sources: