Mockito Getting Started: how some objects in Spring Mock

Recap

With the development of distributed applications becoming standard, a plurality of micro-services team to complete vertical business development has become the norm. Micro Services allowed the team to focus on their business logic, after the upstream and downstream dependency and docking team focused a good interface to enter formal development. However, each team of developers often different rhythm, dependent on the downstream service provided sometimes can not provide a stable service when the self-test. Not only are multiple teams, there will still be a single module dependencies between everyone on the team is responsible, it also exists such a problem.

This time, we need to simulate dependent services in the code, make sure the main flow of the code to develop their own in the post can run through. Once released downstream depend on the service, and then remove the analog service, with real service test again.

Mock service can rely on some of the framework to achieve the most classic is Mockito. Why specifically to look at recent Mock object methods, because prior to Mock downstream services directly modify the source code in. For example, it was supposed to get the user's user ID information based on details from the downstream services, including user name, user age, user gender. However, because the user-centric service has not been released, I realize directly modify the source code, the return of a virtual user information.

public Interface UserService{
  UserInfo getUser(String userId);
}

public Class UserServiceImpl implements UserService() { @Autowired private UserCenter userCenter; @Override public UserInfo getUser(String userId) { //注释了对下游服务的访问 //return userCenter.getUser(userId); //创建了虚拟的用户信息并返回 UserInfo userInfo = new UserInfo(); userInfo.setUserName("xxx"); ... return userInfo; } }

Then, the problem came. After the self-test is completed, I forgot to restore the contents of the source code comments directly submitted to the Mock implement the code repository. Because this service is more than I call a relying party, leading others found that no matter how modifying the user ID, user data obtained is the same when calling this interface. As a result, I began to understand how, without modifying the source code of the service Mock, again to avoid such a problem.

Mockito

Mockito Java unit testing is one of the highest rates Mock framework. It attracted a large number of developers through concise grammar and complete documentation. Mockito support the use of Maven and Gradle to rely on the introduction and management. Examples given here only introduced in dependence Maven:

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <scope>test</scope>
        </dependency>

In the following two Mockito JUnit framework as the basis and is described in detail

Need to test Service

Dependent services 1, name method returns the name

public interface ReliedService {

    String name(); } @Service public class ReliedServiceImpl implements ReliedService { @Override public String name() { return "rale"; } }

Dependent services 2, welcome method returns a welcome message

public interface WelcomeLanguageService {

    String welcome(); } @Service public class WelcomeLanguageServiceImpl implements WelcomeLanguageService { @Override public String welcome() { return "wow"; } }

The need for testing services DemoService.

public interface DemoService {

    String hello(); } @Service public class DemoServiceImpl implements DemoService{ private ReliedService reliedService; private WelcomeLanguageService welcomeLanguageService; @Override public String hello() { return welcomeLanguageService.welcome() + " " + reliedService.name(); } //之所以采用setter的方式进行依赖注入,是为了实现Mock对象的注入 @Autowired public void setReliedService(ReliedService reliedService) { this.reliedService = reliedService; } @Autowired public void setWelcomeLanguageService(WelcomeLanguageService welcomeLanguageService) { this.welcomeLanguageService = welcomeLanguageService; } }

Mock open

Method 1. Mockito.mock

Mockito provided directly mock method which can simulate an example of a service. Simulation complete syntax recombination method when / thenReturn or the like.

import static org.mockito.Mockito.*;

@DelegateTo(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = { Application.class })
public class MockDemo1 { private DemoService demoService; @Before public void before() { demoService = mock(DemoService.class); } @Test public void test() { when(demoService.hello()).thenReturn("hello my friend"); System.out.println(demoService.hello()); verify(demoService).hello(); } }

方法2. MockitoAnnotations.initMocks(this)

Here are achieved when using a first @Mock Mock annotation objects, i.e. using MockitoAnnotations.initMocks (testClass).

@DelegateTo(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = { Application.class })
public class MockDemo2 { @Mock private DemoService demoService; @Before public void before() { MockitoAnnotations.initMocks(this); } @Test public void test() { when(demoService.hello()).thenReturn("hello rale"); System.out.println(demoService.hello()); verify(demoService).hello(); } }

Method 3. @RunWith (MockitoJUnitRunner.class) (recommended)

After put this comment on the test, they are free to use @Mock Mock objects to it.

@RunWith(MockitoJUnitRunner.class)
@DelegateTo(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = { Application.class })
public class MockDemo3 { @Mock private DemoService demoService; @Test public void test() { when(demoService.hello()).thenReturn("hello rale"); System.out.println(demoService.hello()); verify(demoService).hello(); } }

Method 4. MockitoRule

It should be noted that if the use of MockitoRule words, the level of access that object must be public.

@RunWith(JUnit4.class)
@DelegateTo(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = { Application.class })
public class MockDemo4 { @Rule public MockitoRule rule = MockitoJUnit.rule(); @Mock private DemoService demoService; @Test public void test() { when(demoService.hello()).thenReturn("hello rale"); System.out.println(demoService.hello()); verify(demoService).hello(); } }

In the above four methods, the most recommended is the second method, if you can not use @RunWith(MockitoJUnitRunner.class)the time, and then consider other compatible method.

Stub

Stub standards have been given in the above simple example, based on the current Mockito BDD (Behavior Driven Development) also provides a similar thought given / willReturn syntax. However, Spring equally as IOC framework, and integration of Mockito there are some problems. That is, if required on the part of the dependent Spring Bean performed Stub, the need to manually set.

Mockito actually provides a very convenient annotation is called @InjectMocks, Mock objects that comment will be automatically declared the test cell is injected into the Bean in. But I met in the course of the experiment in question, that is, @InjectMocksif you want to mark on the interface, the interface must be manually initialized, otherwise it will throw an exception could not be initialized interface. However, without using the automatic injector Spring, you must manually type in the other dependent injection into Bean.

Therefore, currently used Mockito compromise is directly @Autowire implementation of this interface. In the above InjectMocks annotation tag then, at this time will test Mock objects declared automatically injected, while the dependent object not declared dependency injection is still using the Spring Bean:

@RunWith(MockitoJUnitRunner.class)
@DelegateTo(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = { Application.class })
public class InjectMockTest { @Mock private WelcomeLanguageService welcomeLanguageService; @Autowired @InjectMocks private DemoServiceImpl demoService; @Before public void before() { MockitoAnnotations.initMocks(this); given(welcomeLanguageService.welcome()).willReturn("hahaha"); } @Test public void test() { System.out.println(demoService.hello()); } }

DemoService in, WelcomeLanguageService use Mock Objects, and ReliedService will automatically injected using the Spring Bean.

Reference article

Mockito official documents

Guess you like

Origin www.cnblogs.com/exmyth/p/12535900.html