Service integration tests not reusing application context (fixed!)

Hey everyone,

If you have been doing local development of any of the microservices (reference data in particular), you may have noticed that running a local build takes a significant amount of time. For example, the reference data service takes about 15 minutes on my dev machine. The bulk of the time is spent running integration tests and web integration tests specifically. This is because each integration test class starts a new Spring application context for the tests to run. Spring used to reuse the application context for all web integration tests, but this stopped happening around when each service moved to Spring Boot 1.4. On Friday, I discovered why and successfully found a workaround.

There is an online discussion about the issue here: https://github.com/spring-projects/spring-boot/issues/7174 . It has to do with the mock beans (@MockBean annotation). Because each integration test class had a different set of mock beans, Spring was not able to reuse the application context and had to create a new one each time. The workaround is to put all of the mock beans that any test class would need, into the superclass (BaseWebIntegrationTest). This ensures all tests are using the same set of mock beans and therefore, same application context.

Making this change has sped up our build process. A local build (of the reference data service) on my dev machine has shortened from 15 minutes to 5 minutes. The same build on the CI server has also reduced from 5.5 minutes to 2.5 minutes. The time savings will increase as we add more integration tests.

We will need to implement this workaround for integration tests to other services to speed up build times there as well.

Shalom,

Chongsun

– ​

There are 10 kinds of people in this world; those who understand binary, and those who don’t.

Chongsun Ahn | chongsun.ahn@villagereach.org

Software Development Engineer

Village****Reach* ** Starting at the Last Mile*

2900 Eastlake Ave. E, Suite 230, Seattle, WA 98102, USA

DIRECT: 1.206.512.1536 **CELL: **1.206.910.0973 FAX: 1.206.860.6972

SKYPE: chongsun.ahn.vr

www.villagereach.org

Connect on Facebook****, Twitter** ** and our Blog

This is great! Thanks for figuring this one out. As you know I was banging my head against the wall with these cumbersome tests.

As we’re opening up the integration tests here, I’m wondering if we would expect the context to be re-used if we used a “factory” to return mock singleton beans? This inheritance hierarchy feels brittle, and while I can see the use of inheritance for the repository integration tests (a little reluctantly), I’m wondering if we could be testing more concisely by breaking up this inheritance structure of *ControllerIntegrationTest and looking at some of the newer testing annotations such as @WebMvcTest and @JsonTest.

···

On Monday, July 24, 2017 at 9:09:40 AM UTC-7, chongsun.ahn wrote:

Hey everyone,

If you have been doing local development of any of the microservices (reference data in particular), you may have noticed that running a local build takes a significant amount of time. For example, the reference data service takes about 15 minutes on my dev machine. The bulk of the time is spent running integration tests and web integration tests specifically. This is because each integration test class starts a new Spring application context for the tests to run. Spring used to reuse the application context for all web integration tests, but this stopped happening around when each service moved to Spring Boot 1.4. On Friday, I discovered why and successfully found a workaround.

There is an online discussion about the issue here: https://github.com/spring-projects/spring-boot/issues/7174 . It has to do with the mock beans (@MockBean annotation). Because each integration test class had a different set of mock beans, Spring was not able to reuse the application context and had to create a new one each time. The workaround is to put all of the mock beans that any test class would need, into the superclass (BaseWebIntegrationTest). This ensures all tests are using the same set of mock beans and therefore, same application context.

Making this change has sped up our build process. A local build (of the reference data service) on my dev machine has shortened from 15 minutes to 5 minutes. The same build on the CI server has also reduced from 5.5 minutes to 2.5 minutes. The time savings will increase as we add more integration tests.

We will need to implement this workaround for integration tests to other services to speed up build times there as well.

Shalom,

Chongsun

– ​

There are 10 kinds of people in this world; those who understand binary, and those who don’t.

Chongsun Ahn | chongsun.ahn@villagereach.org

Software Development Engineer

Village****Reach* ** Starting at the Last Mile*

2900 Eastlake Ave. E, Suite 230, Seattle, WA 98102, USA

DIRECT: 1.206.512.1536 **CELL: **1.206.910.0973 FAX: 1.206.860.6972

SKYPE: chongsun.ahn.vr

www.villagereach.org

Connect on Facebook****, Twitter** ** and our Blog

Hi,

This is great improvement. Couple of weeks ago I wrote ticked for improve integration tests in Fulfillment service because they are very slow. I have updated ticket description so it points to this topic. https://openlmis.atlassian.net/browse/OLMIS-2734

···

On Monday, July 24, 2017 at 6:09:40 PM UTC+2, chongsun.ahn wrote:

Hey everyone,

If you have been doing local development of any of the microservices (reference data in particular), you may have noticed that running a local build takes a significant amount of time. For example, the reference data service takes about 15 minutes on my dev machine. The bulk of the time is spent running integration tests and web integration tests specifically. This is because each integration test class starts a new Spring application context for the tests to run. Spring used to reuse the application context for all web integration tests, but this stopped happening around when each service moved to Spring Boot 1.4. On Friday, I discovered why and successfully found a workaround.

There is an online discussion about the issue here: https://github.com/spring-projects/spring-boot/issues/7174 . It has to do with the mock beans (@MockBean annotation). Because each integration test class had a different set of mock beans, Spring was not able to reuse the application context and had to create a new one each time. The workaround is to put all of the mock beans that any test class would need, into the superclass (BaseWebIntegrationTest). This ensures all tests are using the same set of mock beans and therefore, same application context.

Making this change has sped up our build process. A local build (of the reference data service) on my dev machine has shortened from 15 minutes to 5 minutes. The same build on the CI server has also reduced from 5.5 minutes to 2.5 minutes. The time savings will increase as we add more integration tests.

We will need to implement this workaround for integration tests to other services to speed up build times there as well.

Shalom,

Chongsun

– ​

There are 10 kinds of people in this world; those who understand binary, and those who don’t.

Chongsun Ahn | chongs...@villagereach.org

Software Development Engineer

Village****Reach* ** Starting at the Last Mile*

2900 Eastlake Ave. E, Suite 230, Seattle, WA 98102, USA

DIRECT: 1.206.512.1536 **CELL: **1.206.910.0973 FAX: 1.206.860.6972

SKYPE: chongsun.ahn.vr

www.villagereach.org

Connect on Facebook****, Twitter** ** and our Blog