웹사이트 검색

Mockito @InjectMocks - Mocks 종속성 주입


Mockito @Spy 주석.

모키토 @InjectMocks

Mockito는 지정된 순서대로 세 가지 접근 방식 중 하나를 사용하여 모의 종속성을 주입하려고 시도합니다.

  1. 생성자 기반 주입 - 클래스에 대해 정의된 생성자가 있는 경우 Mockito는 가장 큰 생성자를 사용하여 종속성을 주입하려고 시도합니다.
  2. Setter 메소드 기반 - 정의된 생성자가 없을 때 Mockito는 setter 메소드를 사용하여 종속성을 주입하려고 시도합니다.
  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;
	}
}

종속성이 있는 App Service 클래스

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 Tutorial을 얻게 됩니다.

@InjectMocks Setter 메소드 주입 예제

@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"));
	
}

GitHub 리포지토리에서 전체 코드와 더 많은 Mockito 예제를 확인할 수 있습니다.

참조: API 문서