Поиск по сайту:

Mockito @InjectMocks — имитация внедрения зависимостей


Аннотации Mockito @Spy.

Мокито @InjectMocks

Mockito пытается внедрить фиктивные зависимости, используя один из трех подходов в указанном порядке.

  1. Внедрение на основе конструктора. Когда для класса определен конструктор, Mockito пытается внедрить зависимости, используя самый большой конструктор.
  2. На основе методов установки. Если конструкторы не определены, Mockito пытается внедрить зависимости с помощью методов установки.
  3. На основе поля — если конструкторы или внедрение на основе полей невозможно, mockito пытается внедрить зависимости в само поле.

Если есть только один соответствующий фиктивный объект, mockito вставит его в объект. Если имеется более одного фиктивного объекта одного и того же класса, то имя фиктивного объекта используется для внедрения зависимостей.

Макет @InjectMocks Пример

Давайте создадим несколько сервисов и классов с зависимостями, чтобы мы могли увидеть внедрение моков Mockito в действии. Классы обслуживания

package com.journaldev.injectmocksservices;

public interface Service {

	public boolean send(String msg);
}
package com.journaldev.injectmocksservices;

public class EmailService implements Service {

	@Override
	public boolean send(String msg) {
		System.out.println("Sending email");
		return true;
	}

}
package com.journaldev.injectmocksservices;

public class SMSService implements Service {

	@Override
	public boolean send(String msg) {
		System.out.println("Sending SMS");
		return true;
	}
}

Классы службы приложений с зависимостями

package com.journaldev.injectmocksservices;

//For Constructor Based @InjectMocks injection
public class AppServices {

	private EmailService emailService;
	private SMSService smsService;

	public AppServices(EmailService emailService, SMSService smsService) {
		this.emailService = emailService;
		this.smsService = smsService;
	}

	public boolean sendSMS(String msg) {
		return smsService.send(msg);
	}

	public boolean sendEmail(String msg) {
		return emailService.send(msg);
	}
}
package com.journaldev.injectmocksservices;

//For Property Setter Based @InjectMocks injection
public class AppServices1 {

	private EmailService emailService;
	private SMSService smsService;

	public void setEmailService(EmailService emailService) {
		this.emailService = emailService;
	}

	public void setSmsService(SMSService smsService) {
		this.smsService = smsService;
	}

	public boolean sendSMS(String msg) {
		return smsService.send(msg);
	}

	public boolean sendEmail(String msg) {
		return emailService.send(msg);
	}

}
package com.journaldev.injectmocksservices;

//For Field Based @InjectMocks injection
public class AppServices2 {

	private EmailService emailService;
	private SMSService smsService;

	public boolean sendSMS(String msg) {
		return smsService.send(msg);
	}

	public boolean sendEmail(String msg) {
		return emailService.send(msg);
	}

}

Пример внедрения конструктора @InjectMocks

package com.journaldev.mockito.injectmocks;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import com.journaldev.injectmocksservices.AppServices;
import com.journaldev.injectmocksservices.AppServices1;
import com.journaldev.injectmocksservices.AppServices2;
import com.journaldev.injectmocksservices.EmailService;
import com.journaldev.injectmocksservices.SMSService;

class MockitoInjectMocksExamples extends BaseTestCase {

	@Mock EmailService emailService;
	
	@Mock SMSService smsService;
	
	@InjectMocks AppServices appServicesConstructorInjectionMock;
	
	@InjectMocks AppServices1 appServicesSetterInjectionMock;
	
	@InjectMocks AppServices2 appServicesFieldInjectionMock;
	
	@Test
	void test_constructor_injection_mock() {
		when(appServicesConstructorInjectionMock.sendEmail("Email")).thenReturn(true);
		when(appServicesConstructorInjectionMock.sendSMS(anyString())).thenReturn(true);
		
		assertTrue(appServicesConstructorInjectionMock.sendEmail("Email"));
		assertFalse(appServicesConstructorInjectionMock.sendEmail("Unstubbed Email"));
		
		assertTrue(appServicesConstructorInjectionMock.sendSMS("SMS"));
		
	}
}

Вы заметили, что мой тестовый класс расширяет BaseTestCase. Это нужно для инициализации моков Mockito перед тестами, вот код класса.

package com.journaldev.mockito.injectmocks;

import org.junit.jupiter.api.BeforeEach;
import org.mockito.MockitoAnnotations;

class BaseTestCase {

	@BeforeEach
	void init_mocks() {
		MockitoAnnotations.initMocks(this);
	}

}

Если вы не будете вызывать MockitoAnnotations.initMocks(this);, вы получите учебник по JUnit 5.

Пример внедрения методов установки @InjectMocks

@Test
void test_setter_injection_mock() {
	when(appServicesSetterInjectionMock.sendEmail("New Email")).thenReturn(true);
	when(appServicesSetterInjectionMock.sendSMS(anyString())).thenReturn(true);
	
	assertTrue(appServicesSetterInjectionMock.sendEmail("New Email"));
	assertFalse(appServicesSetterInjectionMock.sendEmail("Unstubbed Email"));
	
	assertTrue(appServicesSetterInjectionMock.sendSMS("SMS"));
	
}

@InjectMocks Пример внедрения на основе поля

@Test
void test_field_injection_mock() {
	when(appServicesFieldInjectionMock.sendEmail(anyString())).thenReturn(true);
	when(appServicesFieldInjectionMock.sendSMS(anyString())).thenReturn(true);
	
	assertTrue(appServicesFieldInjectionMock.sendEmail("Email"));
	assertTrue(appServicesFieldInjectionMock.sendEmail("New Email"));
	
	assertTrue(appServicesFieldInjectionMock.sendSMS("SMS"));
	
}

Вы можете ознакомиться с полным кодом и другими примерами Mockito в нашем репозитории GitHub.

Ссылка: документ API