在呼叫层次结构中插入模拟的对象



我正在编写我的第一个单元测试(使用Mockito(。我希望测试的功能的结构如下:

class ClassA {
    public ClassB b;
    public void methodA() {
        // calls a method of ClassB
        b.methodB();
    }
}
class ClassB {
    public ClassC c;
    public void methodB() {
        // calls a method of ClassC
        someVariable = c.methodC();
    }
}
class ClassC {
    public Object methodC() {
        // do something
        // this method needs to be mocked for testing (needs to return dummy values to ClassB)
    }
}

我真正希望测试的是我在ClassB中引入的某种功能是否仍然有效。为此,我需要 methodC()(从 ClassB被调用(才能返回某些值,因此我模拟了 ClassC

我的问题是,我遇到的所有教程都没有显示从另一个类调用正在调用的类别的课程(例如,在我的情况下-ClassBClassA调用(。

另外,教程显示了被模拟的类测试的实例,与我的情况不同(我正在测试ClassB,但需要模拟ClassC(。

我应该如何为ClassB编写单元测试?我对本单元测试的想法如下:

@RunWith(MockitoJUnitRunner.class)
class TestB {
    public ClassA instanceA;
    public ClassB instanceB;
    @Mock
    public ClassC instanceC;        
    public void setUp() {
        // do setup stuff
        when(instanceC.methodC()).thenReturn(dummyValue);
        b.setC(instanceC);
    }
    @Test
    public void Test() {
    }
}

我还没有尝试过,但是我想知道这种方法是否合理,或者我的单位测试是否被错误建模。谢谢!

我的问题是,我遇到的所有教程都没有显示正在从另一个类中调用的班级

您不必担心。当您测试ClassB时,您无需考虑其呼叫者。目前,您唯一的目标是测试ClassB的功能。

因此,您可以从TestB类中删除public ClassA instanceA;。您的setUp方法看起来不错。

这是您的测试方法的外观

@Test
public void test_methodB() {
    instanceB.methodB();
    //Rest depends on the logic within methodB. Maybe use Mockito verify to verify certain calls were made, use Answers etc.
}

此外,教程显示了被模拟的类测试类的实例

我不明白为什么需要模拟正在测试的系统。

正如User7所提到的,您绝不应该模拟正在测试的类。模拟应用于模拟依赖类,以便您不必创建依赖类(以便说它在其构造函数中需要3个参数,并且每个参数都需要进一步的参数来构造它们;为了避免这种情况,我们使用模拟(。您可以模拟它并设置预期行为(使用when(mockedObject.someMethod()).return(dummyValue)(并仅测试您的类,而不是创建依赖的类实例。如果依赖的班级的行为应应有的,我的班级会按照我的期望表现?因此,您的设置方法是正确的。您从ClassC设置了期望,您将测试您的classB。

只是要订购 @user7所说的话,以使一些更容易。

  1. 您应该有3个测试词组(ClassAtest,classBtest,classCtest(
  2. 在ClassAtest中,您应该模拟使用的classB实例,并确保在instacea.methoda(((您可以查找Mockito.verify(上调用方法B。
  3. 在classbtest中,您应该模拟使用classc的实例,并确保在instaceb.methodb((上调用methodc(与以前相同,也请查看InpoctMocks注释(

    @RunWith(MockitoJUnitRunner.class)
    class TestB {
      @InjectMocks
      public ClassB instanceB;
      @Mock
      public ClassC instanceC;        
      public void setUp() {
        // do setup stuff
        when(instanceC.methodC()).thenReturn(dummyValue);
      }
      @Test
      public void Test() {
        instaceB.methodB();
      }
    }
    
  4. 在ClassCtest中,您应该在Methodc上测试所有逻辑。

最新更新