英文:
Deep mocking with Mockito and Spring Boot
问题
我需要使用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;
/* 看,我需要模拟Aclass,而不是Bclass或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。
这是可能的吗?
英文:
I need to mock (with Mockito) the "A" class used by "B" class however my test case is done to "D" class.
See my example:
@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);
}
}
My test is :
@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);
}
}
It was a simple example of what I need.
When I run this I received NullPointerException in Dclass.
Is it possible ?
答案1
得分: 1
我认为你应该使用Mockito这样来测试你的Bclass类:
public class BclassTest {
Long a = 0L;
Long b = 0L;
Long c = 1L;
@InjectMocks
private Bclass bclass;
@Mock
private Aclass aclass;
// 你应该在@Before方法中初始化你的Mock对象。
@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(a, b, c));
}
}
英文:
I Think You should Test Your class Bclass with Mockito Like this :
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));
}
}
}
答案2
得分: 1
根据示例代码,很明显以下服务的依赖关系如下:
- Dclass 依赖于 Cclass
- Cclass 依赖于 Bclass
- Bclass 依赖于 Aclass
当我们为 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; // 现在它有所有三个模拟对象(但不需要 A 和 B 的模拟)
@Mock Aclass classA; // 不需要(Dclass 不依赖于 Aclass)
@Mock Bclass classB; // 不需要(Dclass 不依赖于 Bclass)
@Mock Cclass classC; // **必需** - 因为 Dclass 直接依赖于 Cclass
根据您的代码 - 您为 Aclass 创建了一个模拟对象,并将其注入到了 Dclass 中。
为 Aclass 模拟对象编写了 When(...).then(...)。
@Test
public void testSunFourNumbers(){
Mockito.when(classA.sumTwoNumbers(any(Long.class), any(Long.class))).thenReturn(0L);
// 由于您的代码中没有针对 'classC' 的模拟对象,它将为 null,导致空指针异常
Long sum = classC.sunFourNumbers(1L, 1L, 1L, 1L);
Assert.assertEquals(2L, sum);
}
英文:
As per the example code, its pretty clear that below services dependent as below
- DClass depends on Cclass
- Cclass on Bclass and
- Bclass on Aclass
When we write unit test cases for Dclass (code as below),
@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);
}
}
Here Dclass is directly dependent on Cclass, so mocking Cclass is enough in this case. Unit testing is all about testing a small unit by mocking its direct dependents.
@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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论