0

I have a Spring boot project that I'm migrating to Spring boot 2. Some of my tests that where working with the previous version are failing with the new version.

The issue is easy to reproduce.

I create 2 Controller. In the first, I inject a Service. In the second, I inject a JpaRepository.

Now I create UnitTests for both this Controller. For the second Controller, I mock the Repository. Everything works fine. For the first Controller, I mock the Service. The test fail. It seems to search to inject the Repository whereas it is not used in this Controller.

I create a very simple project to reproduce this behavior : https://github.com/YLombardi/mockito-spring-jpa-issue

Is it my test that is wrong or a bug ?

1 Answer 1

1

I was able to reproduce the issue from the repo url you gave. If you notice the exception when you run ControllerAUnitTests, it says

...UnsatisfiedDependencyException: Error creating bean with name 'controllerB'...

Now, why would spring try to load controllerB bean when you are running tests for ControllerA?

This is because you are using SpringRunner and default mockMvc. It loads whole spring context that means it will create beans of every component including controllerB.

To create the bean of controllerB, you need to have an instance of JpaRepo. So, just like you created mocked bean of ServiceA in ControllerAUnitTests, you need to create mocked bean for JpaRepo as well.

 @MockBean private ServiceA serviceA; // NOTE THIS BLOCK @MockBean private JpaRepo jpaRepo; @Test public void test() throws Exception { doReturn("a").when(serviceA).getAString(); mockMvc.perform(get("/a")) .andDo(print()) .andExpect(status().isOk()) // Test now runs but assert fails below, that you need to fix. .andExpect(view().name("aview")) .andExpect(content().string("a")); } 
Sign up to request clarification or add additional context in comments.

4 Comments

So I need to mock the JpaRepo in every test classes ? Even if It is not used in the Controller. It's seems weird. With the previous spring version, we needed to mock only the component that were injected in the class that is tested.
By default MockMvc is loaded with all context. If you just want to have context for a single controller, create standalone context using MockMvcBuilders.standaloneSetup....
"We needed to mock only the component that were injected in the class that is tested" - True when you are running test with MockitoJunitRunner.
Thanks, I understand my mistake. The new annotation @WebMvcTest does not replace the need to configure the MockMvcBuilders.standaloneSetup(controllerA).build();

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.