简体   繁体   English

在 Java 和 Spring 的单元测试中使用 mocking 的接口

[英]Using an interface for mocking purposes in unit tests for Java with Spring

I have a problem trying to mock interfaces in my API based on Spring.我在尝试模拟基于 Spring 的 API 中的接口时遇到问题。 I am getting this error:我收到此错误:

Description:

Parameter 0 of constructor in bm.app.services.Service required a bean of type 'bm.app.services.DiscountProvider' that could not be found.


Action:

Consider defining a bean of type 'bm.app.services.DiscountProvider' in your configuration.

And I just don't understand it.我就是不明白。 I am adding an interface (DiscountProvider) as a parameter for a constructor of my service class (Service) in order to use Mockito for testing purposes.我正在添加一个接口 (DiscountProvider) 作为我的服务 class (Service) 的构造函数的参数,以便将 Mockito 用于测试目的。

The beginning of my Service (I think the only relevant part here) looks like this:我的服务的开始(我认为这里唯一相关的部分)如下所示:

@org.springframework.stereotype.Service
public class Service {

    DiscountProvider discountProvider;

    public Service(DiscountProvider discountProvider) {
        this.discountProvider = discountProvider;
    }

The interface looks like this:界面如下所示:

import org.springframework.stereotype.Component;

import java.math.BigDecimal;

@Component
public interface DiscountProvider {

    BigDecimal getThePriceOfTheProduct();
}

And my test class looks like that:我的测试 class 看起来像这样:

@Component
public class ServiceTests {

    Service service;
    DiscountProvider discountProvider;

    @Test
    @DisplayName("Should return the value higher by ten percent.")
    void shouldReturnValueHigherByTenPercent() {
        //given
        Mockito.when(discountProvider.getThePriceOfTheProduct()).thenReturn(new BigDecimal("20.00"));
        AdditionalMiniProduct product = new AdditionalMiniProduct(UUID.randomUUID(), new BigDecimal("300.00"), "Yellow Loan");
        //when
        BigDecimal result = service.increaseByGivenAmount(product.getNetPrice(), discountProvider.getThePriceOfTheProduct());
        //then
        assertThat(result).isEqualTo("315.00");
    }

    @Test
    void shouldReturnACorrectRiskLevelValue() {
        int months = 18;
        assertEquals(5, calculateRiskLevelByNumberOfMonths(months));
    }

    @Test
    void shouldReturnACorrectEnumValueBasedOnNumberOfMonths() {
        int months = 26;
        assertEquals(RiskLevel.HIGH, giveTheRiskNameBasedOnNumberOfMonths(months));
    }

    @Test
    void shouldReturnAPriceOfAProvidedFinancialProduct() {
        BigDecimal productPrice = new BigDecimal(1200);
        String productName = "SilverLoan";
        assertEquals(productPrice,findAProductPriceByGivenName(productName));
    }

    @BeforeEach
    void setUp() {
        service = new Service(discountProvider);
        discountProvider = Mockito.mock(DiscountProvider.class);
    }


}

Now, I am fairly new to testing, so I do expect to have made some rookie mistakes.现在,我对测试还很陌生,所以我确实预计会犯一些新手错误。 The thing is, that's my first attempt to have more "complex" unit tests run with one of my Spring apps and I just don't get it.问题是,这是我第一次尝试使用我的 Spring 应用程序运行更“复杂”的单元测试,但我就是不明白。 It refuses to acknowledge the @Component (or any other I managed to find) annotation.它拒绝承认@Component(或我设法找到的任何其他)注释。

If you are unit testing your Service class, you should mock all external dependencies of this class under test.如果您正在对Service class 进行单元测试,则应模拟此 class 的所有外部依赖项。

Assuming you are using JUnit 5, a possible test setup can look like the following假设您使用的是 JUnit 5,可能的测试设置如下所示

@ExtendWith(MockitoExtension.class)
public class ServiceTest {

  @Mock
  private DiscountProvider discountProvider;

  @InjectMocks
  private Service service;

  @Test
  @DisplayName("Should return the value higher by ten percent.")
  void shouldReturnValueHigherByTenPercent() {
    //given
    Mockito.when(discountProvider.getThePriceOfTheProduct()).thenReturn(new BigDecimal("20.00"));
    AdditionalMiniProduct product = new AdditionalMiniProduct(UUID.randomUUID(), new BigDecimal("300.00"), "Yellow Loan");
     
    //when
    BigDecimal result = service.increaseByGivenAmount(product.getNetPrice(), discountProvider.getThePriceOfTheProduct());

    //then
    assertThat(result).isEqualTo("315.00");
  }

}

In addition, you don't need @Component for your test classes.此外,您的测试类不需要@Component This annotation is used for your production code to mark Spring beans.此注释用于您的生产代码以标记 Spring bean。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM