【问题标题】:Avoid mocking underlying method calls for Mock Objects in Junit避免在 Junit 中模拟对 Mock 对象的底层方法调用
【发布时间】:2021-05-21 18:17:18
【问题描述】:

下面是我的代码。 RestTemplateFactoryForMyApp 是从我获得 RestTemplate 对象的地方。 在我正在测试的其他类 RestTemplateExampleClass 中。我如下使用它,它工作正常。我已经将 JUnit 编写到 RestTemplate 调用,它也可以正常工作。 但是当我在我的 JUnit 测试类中将以下代码注释为 restTemplateFactoryForMyApp.restTemplate()=NULL 时,我得到 NullPointerException。我怎样才能避免这种情况?假设我在 RestTemplateFactoryForMyApp 中调用了 10 个不同的类方法,那么我也必须为它们做同样的事情。那么如何避免呢?

@Configuration
public class RestTemplateFactoryForMyApp {
    
    @Bean
    public RestTemplate restTemplate() {
    
    return new RestTemplate();
}


    

given(restTemplateFactoryForMyApp.restTemplate()).willReturn(restTemplate);
    private final RestTemplate restTemplate = mock(RestTemplate.class);






@Autowired
    private RestTemplateFactoryForMyApp restTemplateFactoryForMyApp;
    
restTemplateFactoryForMyApp.restTemplate().exchange

下面是我的 JUnit 测试 restTemplate 调用

@ExtendWith(MockitoExtension.class)
public class RestTemplateExampleTest {

    @Mock
    private RestTemplateFactoryForMyApp restTemplateFactoryForMyApp;

    @InjectMocks
    private RestTemplateExample restTemplateExample ;
    
    private final RestTemplate restTemplate = mock(RestTemplate.class);

    
    
    @BeforeEach
    void setUp() throws Exception {
        given(restTemplateFactoryForMyApp.restTemplate()).willReturn(restTemplate);
        ReflectionTestUtils.setField(restTemplateExample, "id", 1);
    }

    @Test
    public void mock_resttemplate() {
        TodosObject todosObject = new TodosObject();
        todosObject.setId(1);
        
        
        System.out.println(" restTemplateFactoryForMyApp "  + restTemplateFactoryForMyApp.restTemplate());
        
        int i = (int) ReflectionTestUtils.getField(restTemplateExample, "id");
        
        System.out.println( " value of i " + i);
        
        Mockito
          .when(restTemplateFactoryForMyApp.restTemplate().exchange(
                "https://jsonplaceholder.typicode.com/todos/" + i,
                HttpMethod.GET,
                null,
                TodosObject.class
        ))
          .thenReturn(new ResponseEntity<TodosObject>(todosObject, HttpStatus.OK));

【问题讨论】:

    标签: spring spring-boot junit mocking mockito


    【解决方案1】:

    我不完全确定您的问题,但也许 RETURNS_DEEP_STUBS 有帮助:

    @ExtendWith(MockitoExtension.class)
    public class RestTemplateExampleTest {
    
        @Mock(answer = RETURNS_DEEP_STUBS) 
        private RestTemplateFactoryForMyApp restTemplateFactoryForMyApp;
    
        @InjectMocks
        private RestTemplateExample restTemplateExample;
        
        @BeforeEach
        void setUp() throws Exception {
            ReflectionTestUtils.setField(restTemplateExample, "id", 1);
        }
    
        @Test
        public void mock_resttemplate() {
            TodosObject todosObject = new TodosObject();
            todosObject.setId(1);
            
            
            System.out.println(" restTemplateFactoryForMyApp "  + restTemplateFactoryForMyApp.restTemplate());
            
            int i = (int) ReflectionTestUtils.getField(restTemplateExample, "id");
            
            System.out.println( " value of i " + i);
            
            Mockito
              .when(restTemplateFactoryForMyApp.restTemplate().exchange(
                    "https://jsonplaceholder.typicode.com/todos/" + i,
                    HttpMethod.GET,
                    null,
                    TodosObject.class
            ))
              .thenReturn(new ResponseEntity<TodosObject>(todosObject, HttpStatus.OK));
    

    【讨论】:

    • 我的问题是我需要模拟 RestTemplateFactoryForMyApp 还是模拟 restTemplateFactoryForMyApp.restTemplate()
    • 这取决于你想测试什么。不幸的是,您问题中的测试不完整。一般来说,我认为您必须模拟方法restTemplate()
    猜你喜欢
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多