如何使用 Mockito 框架模拟我的服务

Posted

技术标签:

【中文标题】如何使用 Mockito 框架模拟我的服务【英文标题】:How to mock my service using Mockito framework 【发布时间】:2021-12-27 14:43:43 【问题描述】:

您好,我正在努力按照下面的方法编写一个模拟测试;

下面是我的代码;

@Component
public class CodeConfigBuilder 

    @Value("$promoConfig.prefix.length")
    private Integer prefixLength;

    public void validateRequestAndSetDefaults(PromoRequest promoRequest) 
        prefixAndPostFixControlAccordingToLength(promoRequest);
    

    private void prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest) 
        if (promoRequest.getPostfix() != null) 
            int lengthControl = prefixLength + promoRequest.getPostfix().length();
            if (lengthControl >= promoRequest.getLength()) 
                throw new BadRequestException(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT);
            
            
    

下面是我的yml配置;

 #=========  Promo  Config  ========== #
    
        promoConfig:
          prefix:
            length: 3

下面是我的服务;

public void validateRequest(PromoRequest promoRequest) 
      
        codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
    

我创建了一个 PropertySourceResolver 类

@Component
@Getter
public class PropertySourceResolver 
private int prefixLength = 3;

下面还有我的测试课;

@RunWith(MockitoJUnitRunner.class)
class CodeConfigBuilderTest 

   @MockBean
    private PropertySourceResolver propertySourceResolver = new PropertySourceResolver();
    @InjectMocks
    private PromoRequest promoRequest = new PromoRequest();
    @InjectMocks
    private PromoService Service;

   @Before
    public void init() 

        promoRequest.setPrefix("ABC");
        promoRequest.setPostfix("ABCDABCD");
        promoRequest.setQuantity(10);
        promoRequest.setLength(12);
        promoRequest.setCharset("ABCDEF");
    

    @Test
    public void prefixAndPostFixControl_accordingToLength_for_Succeed() 

        int lengthControl = promoRequest.getPrefix().length() + promoRequest.getPostfix().length();

        if (lengthControl >= promoRequest.getLength()) 
            Assert.assertTrue(false);
        
    

我喜欢根据测试场景更改我的代码,例如;当......然后返回任何想法?谢谢。

【问题讨论】:

到底是什么问题?有什么事情没有按照您的预期工作? 我喜欢更改我的代码: (当...).thenReturn() CodeConfigBuilder 是一个简单的服务,为什么你认为你需要 mockito 来测试它?创建一个有效的PromoRequest 并将其传递给validateRequestAndSetDefaults,它不应该抛出。然后创建一个无效的PromoRequestvalidateRequestAndSetDefaults 会抛出。使用构造函数注入来简化CodeConfigBuilder的创建 所以您希望prefixLength 可以在您的测试中即时调整,对吗? @lesika 你介意写一下怎么做吗谢谢 【参考方案1】:

为了使这更简单和更好地组织您的代码,通过创建以下类来抽象注入配置的复杂性:

@ConfigurationProperties(prefix = "promoConfig.prefix")
public class PromoPrefixConfiguration 
    private Integer length;

    public Integer getLength() 
        return length;
    

然后,您应该将此作为 CodeConfigBuilder 的依赖项:

@Component
public class CodeConfigBuilder 

    private Integer prefixLength;

    public CodeConfigBuilder(PromoPrefixConfiguration promoPrefixConfiguration) 
        this.prefixLength = promoPrefixConfiguration.getLength();
    

    public void validateRequestAndSetDefaults(PromoRequest promoRequest) 
        prefixAndPostFixControlAccordingToLength(promoRequest);
    

    private void prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest) 
        if (promoRequest.getPostfix() != null) 
            int lengthControl = prefixLength + promoRequest.getPostfix().length();
            if (lengthControl >= promoRequest.getLength()) 
                throw new BadRequestException(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT);
            
            
    

现在,为了测试这个类,您必须进行三个测试:

    测试PromoRequest 是否有效,因为postfix 为空; 测试PromoRequest是否有效,因为长度有效; 测试PromoRequest无效,因为长度无效;

它们将类似于以下内容:

class CodeConfigBuilderTest 

    private PromoPrefixConfiguration promoPrefixConfiguration = new PromoPrefixConfiguration(10);
    private CodeConfigBuilder codeConfigBuilder = new CodeConfigBuilder(promoPrefixConfiguration);

    @Test
    public void promoRequestIsValidGivenNullPostfix() 
        // Arrange
        PromoRequest promoRequest = new PromoRequest();
        promoRequest.setPostfix(null);

        // Act
        codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
    

    @Test
    public void promoRequestIsValidGivenValidPrefixPlusPostfixLength() 
        // Arrange
        PromoRequest promoRequest = new PromoRequest();
        promoRequest.setPostfix("ABCD");
        promoRequest.setLength(15);

        // Act
        codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
    

    @Test(expected = BadRequestException.class)
    public void promoRequestIsInvalidGivenInvalidPrefixPlusPostfixLength() 
        // Arrange
        PromoRequest promoRequest = new PromoRequest();
        promoRequest.setPostfix("ABCDEFGH");
        promoRequest.setLength(15);

        // Act
        codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
    

如果您使用的是 JUnit 5,则可以将最后一个测试替换为以下测试,以轻松断言异常消息:

@Test
public void promoRequestIsInvalidGivenInvalidPrefixPlusPostfixLength() 
    // Arrange
    PromoRequest promoRequest = new PromoRequest();
    promoRequest.setPrefix("ABCDEFG");
    promoRequest.setPostfix("HIJKLMN");

    // Act 
    Exception exception = assertThrows(BadRequestException.class, () -> 
        codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
    );

    // Assert
    String exceptionMessage = exception.getMessage();
    assertTrue(exceptionMessage.equals(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT));

P.S.:你的意思是 suffix 而不是 postfix

【讨论】:

比你 Joao Dias 这很棒我的意思是后缀和后缀 togethar 不能大于长度 我的回答对您有帮助还是您还有疑问? Jao Dias 我真的很感激我正在尝试你的解决方案,但是我在 codeConfigBuilder 上得到了第二个参数,它是 public CodeConfigBuilder(PromoRepository promoRepository, PromoCodeConfiguration promoCodeConfiguration) this.promoRepository = promoRepository; this.prefixLength = promoCodeConfiguration.getLength(); promoRepository 如何从类中抽象出这个 repo 也许你不应该,在这种情况下,你需要在你的测试中模拟它并相应地调整它们。如果您创建一个新问题并在此处添加所有详细信息并在此处共享链接,那么会更容易为您提供帮助;)

以上是关于如何使用 Mockito 框架模拟我的服务的主要内容,如果未能解决你的问题,请参考以下文章

Mockito:模拟测试框架的具体介绍与使用

如何使用 mockito 模拟方法?

如何模拟EntityManager?

如何在 Mockito 中模拟全局变量

如何使用 Mockito 在 Spring 中模拟自动装配的 @Value 字段?

如何使用Mockito正确模拟每个循环?