Showing posts with label integration testing. Show all posts
Showing posts with label integration testing. Show all posts

Tuesday, July 22, 2014

Spring: Integration testing under Spring Boot application context but mocking services


Use @MockBean annotation

DEPRACATED:

So I wanted to create some integration tests for an API application that uses Spring Boot. The thing is that I needed to load the same application context as the real applicationm, because Spring Boot performs a bunch of configurations for you, and these were not being loaded in a StandAlone mode.

But also I didn't want to use real services which depend upon real data. Depending on databases for your tests creates fragile tests.

After researching on the web I found this way:


This is the typical Spring-Boot entry point class.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@EnableAutoConfiguration
@ComponentScan
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

A base class having the logic to init the application context.

import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = MyApplication.class)
public abstract class BaseIntegrationTest {

    protected MockMvc mockMvc;
    
    @Autowired
    protected WebApplicationContext wac;

    @Before
    public void setup() {
       
        MockitoAnnotations.initMocks(this);
        this.mockMvc = webAppContextSetup(wac).build();
    }
}

An implementation class mocking a required service class.
public class FooIntegrationTest extends BaseIntegrationTest {

    @Configuration
    public static class TestConfiguration {
        @Bean
        @Primary
        public FooService fooService() {
            return mock(FooService.class);
        }
    }


    @Autowired
    FooService mockFooService;
}

Tuesday, August 27, 2013

Unit testing vs Integration testing

Though question if someone has to decide between the two, Unit testing and integration testing are not mutually exclusive. Both of them have their merits in the world of automating testing. In this page we will discuss the the advantages and disadvantages of each approach, and will try to provide a recommendation to apply in the Commerce site. There is a good on line article we will use as reference (see reference at bottom of this page) as it makes a good comparison of the two.

Difference in a nutshell 


The distinction between unit testing and integration testing is simple. Unit testing focus on the internal functionality of a single class, while integration testing proves functionality of an entire system, validating that all classes work fine together. In unit testing, when a class depends of another to complete an operation, it's common to use mocking technique to break the dependency and worry only about the class being tested. In integration testing all classes are real implementations and reflects the real work flows of the application.

A brief comparison

Let's compare a few aspects between the two methods. 


Driving the design


Not only in theory, but also for personal experience, we know that unit testing helps to enforce correct designed solutions in the code. Let's be honest, if you have big chunk of code in a single class method, you will find that there is no “clean” way to unit test the core logic. You will wish to go back in time and prevent yourself from writing nasty code. 

That's one reason why unit testing should be done very closely with production code. If it is pushed forward, the poor person in charge of the unit testing code will find himself having to apply refactoring, with the fear of breaking already tested approved shiny functionality. No one wants to face business explaining why application went down for applying simple tests. You can always make your QA team to regress test everything, but that makes it more expensive.

Integration testing does not improve the design, as it doesn't depend of the underlying implementations. This is a pro and con at the same time. By one hand you don't have to worry about refactoring the code just to apply testing, but it won't help improving the code which is also a good thing in terms of maintenance productivity.


Easy to write 


Unit tests are easy to write if they are done side to side with production code. It can get complicated if refactoring is required to make the code unit testable. Integration tests are easy to write in general. It can get complicated depending of the configuration required to prepare the setups required to initialize the test, and to finalize it. For example, if a user story requires interaction with a database, some initial setups will be required to leave the database in a particular state. After the test, another code will need to be run to leave the database as it was before running the test. Depending also of the framework used, coding tests in a web application context (in-container testing) can take a while to learn the first time. Once learning curve is passed, it might get easier.


Confidence in the test 


Unit testing provides a good level of confidence in the application code, but since it doesn't test integration among subsystems, it doesn't give the level of confidence an integration test provides. Integration tests are the best for regression testing. 


Fail troubleshooting 


With any type of x-unit, it will be common for a test to fail. That is the all point of the automated tests. To discover when someone screws up the application, breaking the functionality that a test is 
supposedly covering. 

Tests need to be maintained. It means that if a test fails, someone has to spend sometime figuring out what happened with the test. Why it failed? With unit testing is pretty straightforward. The test points the exact class method that failed. With integration testing you don't know at first glance what was the specific code that failed the entire operation. Therefore, it's more difficult to troubleshoot an integration test when it fails.


Documentation


Unit tests and integration tests are both good ways to document the system. Unit tests document the internal implementations. Integration tests documents user stories.


Speed


Unit tests are definitely faster than integration tests. Since integration tests can interact with databases, web services, application framework stacks, etc, they might become very slow. Usually they are not run as usual as unit tests, which are very common for developers to run to verify nothing got broken during development.

Summary Table

Here's a summary table with our rating of the different aspects commented before. This might be a little subjective as any rating system, but it provides a general overview of both methods. You can see each one has its strengths and weaknesses.

Unit Testing
Integration Testing
Confidence in the application
Documentation
Driving the design
Easy to write
Fail Troubleshooting
Friendly with Legacy Code
Speed

Friday, February 22, 2013

Unit, Integration and functional tests


There seems to be confusion among developers when referring to unit, integration and functional tests. It makes it worst when these concepts are also used under different names. The idea of this post is to define clearly these terms using an authority on the field to remove the subjectiveness contra argument.

I will use the definitions proposed by Gerard Meszaros on the book xUnit Test Patterns, Refactoring Test Code.



Unit Tests


Unit tests verify the behavior of a single class or method that is a consequence of a design decision. This behavior is typically not directly related to the requirements except when a key chunk of business logic is encapsulated within the class or method in question. These tests are written by developers for their own use; they help developers describe what “done looks like” by summarizing the behavior of the unit in the form of tests.

Integration Tests


Component tests verify components consisting of groups of classes that collectively provide some service. They fit somewhere between unit tests and customer tests in terms of the size of the SUT being verified. Although some people call these “integration tests” or “subsystem tests,” those terms can mean something entirely different from “tests of a specific larger-grained subcomponent of the overall system.”

Functional Tests



Customer tests verify the behavior of the entire system or application. They typically correspond to scenarios of one or more use cases, features, or user stories. These tests often go by other names such as functional tests, acceptance tests, or end-user tests. Although they may be automated by developers, their key characteristic is that an end user should be able to recognize the behavior specified by the test even if the user cannot read the test representation.




Figure 6.1 A summary of the kinds of tests we write and why. The left column contains the tests we write that describe the functionality of the product at various levels of granularity; we perform these tests to support development.
The right column contains tests that span specific chunks of functionality; we execute these tests to critique the product. The bottom of each cell describes what we are trying to communicate or verify.