This is a short series of how to use Spring in integration testing and unit testing. | ||
---|---|---|
Configurations | Mocking | Testing a REST API |
A custom configuration | Configuration logic |
First, a couple of words about Spring in general as a dependency injection framework. One of the best things in Spring is its simplicity of injection. Regardless of where you are, you pop an @Autowired annotation on a class variable (which could be the test class), and it’s ready for injection. Since it’s injecting the same instance regardless of class, setup for mocks is easy. And regardless of how many layers away the object will be injected, the test has access to it, and doesn’t need to pass it between layers, which requires less code. That is always a good thing.
On the registeration side, with @Configuration classes, you can configure exactly and easily what to inject. Spring Boot allows you to do a bit more with easily bootstrapping a project, along with a bit more help for unit tests and integration tests.
All these make it easy to use (and abuse) writing integration tests. Let’s take a look at a couple of scenarios for integration testing.
For our first example, we have a REST API, that inside it calls a dependency. In integration testing APIs like this, we usually go all the way to the back, but even then, we might want to mock something at the back end, mostly for controlling behavior of our integration test.
First, I want to inject a real object I create. In a @Configuration class I put under the test folder, I create this configuration:
@Configuration public class POJOInjectionConfiguration { @Bean public Student student() { return new Student("Gil", "Star Wars"); } }
Then in the integration test I’ll use the @Configuration class:
@RunWith(SpringRunner.class) @ContextConfiguration(classes = { POJOInjectionConfiguration.class }) public class RealStudioPOJOInjected { @Autowired private Student student; @Test public void nameOfInjectedObject() { assertTrue(student.getName() == "Gil"); } }
That is more of an explanation how Spring works, and obviously, not that useful. In actual integration testing scenarios I use this for injecting POJOs in internal layers, or inject objects that will call dependcies I mock.
If I want to inject a mock instead (let’s say Student wasn’t a POJO), I’ll use a different @Configuration class:
@Configuration public class MockInjectionConfiguration { @Bean public Student student() { Student mockStudent = Mockito.mock(Student.class); when(mockStudent.getName()).thenReturn("Gil"); when(mockStudent.getSubject()).thenReturn("Star Wars"); return mockStudent; } }
And then I can use it in a test:
@RunWith(SpringRunner.class) @ContextConfiguration(classes = { MockInjectionConfiguration.class }) public class MockStudentInjected { @Autowired private Student student; @Test public void nameOfMockReturned() { assertTrue(student.getName() == "Gil"); } }
Now that’s in the test, I can add mocking behavior.
That’s the basic @Configuration stuff. We’ll continue the discussion on configurations and mocking next time.
0 Comments