使用Mockito和Spring Boot进行深度模拟

时间:2020-08-14 22:26:52

标签: java spring-boot mockito

我需要模拟(与Mockito一起使用)“ B”类使用的“ A”类,但是我的测试用例已经完成了“ D”类。

请参阅我的示例:

@Service
public class Aclass {
    public Long sumTwoNumbers(Long a, Long b){
       return a + b;
    }
}

@Service
public class Bclass {
     @Autowired    
     private  Aclass classA;

     public Long sunThreeNumbers(Long a, Long b, Long c){
           return classA.sumTwoNumbers(a, b) + c;
     }
}

@Service
public class Cclass {
     @Autowired    
     private  Bclass classB;

     public Long sunFourNumbers(Long a, Long b, Long c, Long d){
           return classB.sunThreeNumbers(a, b, c) + d;
     }
}

@Service
public class Dclass {
     @Autowired    
     private  Cclass classC;

     public Long sunFourNumbers(Long a, Long b, Long c, Long d){
           return classC.sunFourNumbers(a, b, c, d);
     }
}

我的测试是:

@ExtendWith(MockitoExtension.class)
public class DclassTest{

     @InjectMocks    
     private  Dclass classD;

     @Mock    
     private  Aclass classA; 
     /* Look , I need to mock Aclass , not Bclass or Cclass. */
     
     @Test
     public void testSunFourNumbers(){
        Mockito.when(classA.sumTwoNumbers(any(Long.class), any(Long.class))).thenReturn(0L);

        Long sum = classC.sunFourNumbers(1L, 1L, 1L, 1L);

        Assert.assertEquals(2L, sum);        
     } 
}

这是我需要的一个简单例子。

运行此命令时,我在Dclass中收到NullPointerException。

有可能吗?

2 个答案:

答案 0 :(得分:1)

我认为您应该使用Mockito测试您的Bclass类:

public class BclassTest {

        Long a = 0L;
        Long b = 0L;
        Long c = 1L;
         
         @InjectMocks
         private Bclass bclass;

         @Mock
         private Aclass aclass;
       
         //You Should initialize your Mock Objects in @Before method.
         @Before
         public void setup() {
         MockitoAnnotations.initMocks(this);

         @Test
         public void testSunThreeNumbers(){             
         Mockito.when(aclass.sumTwoNumbers(anyLong(),anyLong())).thenReturn(0L);
         assertEquals(Long.valueOf(1), bclass.sunThreeNumbers(Long a, Long b, Long c));
                }
         }
       }

答案 1 :(得分:1)

根据示例代码,很明显,下面的服务如下所示

  1. DClass取决于Cclass
  2. Cclass on Bclass和
  3. Aclass上的Bclass

当我们为Dclass编写单元测试用例时(如下代码),

@Service
public class Dclass {
     @Autowired    
     private  Cclass classC;

     public Long sunFourNumbers(Long a, Long b, Long c, Long d){
           return classC.sunFourNumbers(a, b, c, d);
     }
}

这里Dclass直接依赖于Cclass,因此在这种情况下,模拟Cclass就足够了。单元测试就是通过模拟直接依赖来测试小型单元。

 @InjectMocks Dclass classD; // It has all 3 mocks now (but A and B mocks not needed)
 @Mock Aclass classA;        //not needed (Dclass not dependent on Aclass)
 @Mock Bclass classB;        //not needed (Dclass not dependent on Bclass)    
 @Mock Cclass classC;        // **Mandatory** - Because Dclass is directly dependent on Cclass
 
 As per your code - you have a mock for Aclass and injected mock into Dclass.
 When(...).then(...) written for Aclass mock.

 @Test
 public void testSunFourNumbers(){

    Mockito.when(classA.sumTwoNumbers(any(Long.class), any(Long.class))).thenReturn(0L);

    //Since you don't have mock for 'classC' in your code, it will go as null and result in nullpointer
    Long sum = classC.sunFourNumbers(1L, 1L, 1L, 1L);

    Assert.assertEquals(2L, sum);        
 }         
相关问题