【问题标题】:Using Mockito to mock a class method inside another class使用 Mockito 在另一个类中模拟一个类方法
【发布时间】:2015-10-14 07:44:24
【问题描述】:

我正在尝试使用 Mockito / JUnit 为这样的函数编写单元测试:

class1 {
 method {
  object1 = class2.method // method that I want to fake the return value
  // some code that I still want to run
 }
}

在 Mockito 中有什么方法可以存根 class2.method 的结果吗?我正在尝试提高 class1 的代码覆盖率,因此我需要调用它的实际生产方法。

我查看了 Mockito API 的 spy 方法,但这会覆盖整个方法,而不是我想要的部分。

【问题讨论】:

    标签: java unit-testing junit mocking mockito


    【解决方案1】:

    我写了一个简单的例子,效果很好,希望对你有帮助:

    Class1 中的method1() 调用Class2 中的method2():

        public class Class1 {
            private Class2 class2 = new Class2();
            public int method1() {
                return class2.method2();
            }
        }
    

    Class2 和 method2() :

        public class Class2 {
            public int method2() {
                return 5;
            }
        }
    

    还有测试:

        import org.junit.Rule;
        import org.junit.Test;
        import org.mockito.InjectMocks;
        import org.mockito.Mock;
        import org.mockito.junit.MockitoJUnit;
        import org.mockito.junit.MockitoRule;
    
        import static org.junit.Assert.assertEquals;
        import static org.mockito.Mockito.when;
    
        public class TestClass1 {
    
            @Mock
            Class2 class2;
    
            @InjectMocks
            Class1 class1;
    
            @Rule
            public MockitoRule mockitoRule = MockitoJUnit.rule();
    
            @Test
            public void testMethod1(){
                when(class2.method2()).thenReturn(29);
                assertEquals(29,class1.method1());
            }
        }
    

    【讨论】:

      【解决方案2】:

      这对我有用:

      public class Class1Test {
      
        Class1 class1;
      
        @Before
        public void setUp() {
          MockitoAnnotations.initMocks(this);
          class1 = new Class1();
        }
      
        @Test
        public void testClass1Method() {
      
          Class2 class2 = Mockito.mock(Class2.class);
          class1.setClass2(class2);
          Mockito.when(
                  class2.class2Method(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn("some response");
      
          String actualResponse = class1
                  .class1Method("12345", "3333", "4444");
          assertEquals("some response", actualResponse);
        }
      }
      

      【讨论】:

      • class1.setClass2(class2);不确定这条线应该做什么
      • class1.setClass2(class2) 正在变魔术!它在 class1 中设置模拟对象。
      • 函数 setClass2 是否定义在某处?
      • @Silencer310 这就是我想知道的,我认为它依赖于Class1 允许传入Class2 实例的设计
      【解决方案3】:

      我想我理解你的问题。让我重新表述一下,您有一个正在尝试测试的函数,并且想要模拟在该函数中调用的函数的结果,但在不同的类中。我已经通过以下方式处理了。

      public MyUnitTest {
          private static final MyClass2 class2 = mock(MyClass2.class);
      
          @Begin
          public void setupTests() {
              when(class2.get(1000)).thenReturn(new User(1000, "John"));
              when(class2.validateObject(anyObj()).thenReturn(true);
          }
      
          @Test
          public void testFunctionCall() {
              String out = myClass.functionCall();
              assertThat(out).isEqualTo("Output");
          }
      }
      

      这样做是在使用 @Before 注释包装的函数中,我正在设置我希望 class2 中的函数如何响应给定的特定输入。然后,从实际测试中,我只是在我想测试的类中调用我试图测试的函数。在这种情况下,myClass.functionCall() 正常运行,您不会覆盖它的任何方法,而只是模拟它从 MyClass2 中的方法(或方法)获得的输出。

      【讨论】:

      • 这个答案不完整,实际上导致有人犯了错误(stackoverflow.com/questions/37762496/…)。我看到了几个问题:1)变量/成员myClass从未被声明或初始化,并且class2从未被传递给它。 2) 注释类 @Begin 不存在 - 它应该是 @Before 或者可能是 @BeforeClass 3) 成员 class2 可能不应该是静态的 - 特别是在使用 @Before 的情况下。应该为每个测试重新创建它。 4) 如果不是所有测试都需要,最好在测试本身中存根 class2。
      猜你喜欢
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-23
      • 2014-05-05
      相关资源
      最近更新 更多