为了账号安全,请及时绑定邮箱和手机立即绑定

如何模拟从类级别对象调用的方法

如何模拟从类级别对象调用的方法

HUWWW 2023-10-12 16:44:40
我正在为 A 类编写单元测试,我想模拟一个方法,但该方法是从类级别对象中良性调用的,我将如何模拟它。让我用例子来解释一下正在测试中的 A 级。public class ClassA {    ClassB objectOfB = new ClassB();    public int add(int a, int b) {        int addition = objectOfB.performCalculation(a,b);        return addition;    }}B类,有一些业务逻辑。  public class ClassB {    public int performCalculation(int a, int b) {        int c = a+b;        System.out.println("I am not mocked, I am actual call");        System.out.println("Returning " + c + " From ClassB");        return c;    }  }笔试import static org.junit.Assert.*;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.InjectMocks;import org.mockito.Mockito;import org.powermock.core.classloader.annotations.PrepareForTest;import org.powermock.modules.junit4.PowerMockRunner;@RunWith(PowerMockRunner.class)@PrepareForTest({ClassA.class, ClassB.class})public class ClassATest {    @InjectMocks    ClassA objA = new ClassA();    @Test    public void testAddFromClassA() throws Exception {        ClassB objB = Mockito.mock(ClassB.class);        Mockito.when(objB.performCalculation(5, 10)).thenReturn(15);        int result = objA.add(5, 10);        assertEquals(result, 15);    }}测试结果:这个测试是通过的,但它不是模拟ClassB的方法,而是执行实际的调用。
查看完整描述

1 回答

?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

模拟类的初始化,以便在执行测试时使用模拟


@RunWith(PowerMockRunner.class)

@PrepareForTest({ClassA.class}) //prepare the class creating the new instance of ClassB for test, not the ClassB itself.

public class ClassATest {

    @Test

    public void testAddFromClassA() throws Exception {

        int expected = 15;

        ClassB objB = Mockito.mock(ClassB.class);

        Mockito.when(objB.performCalculation(5, 10)).thenReturn(expected);


        //mocking initialization of ClassB class withing ClassA class

        PowerMockito.whenNew(ClassB.class).withNoArguments().thenReturn(objB);


        ClassA objA = new ClassA();


        //Act

        int actual = objA.add(5, 10);


        //Assert

        assertEquals(expected, actual);

    }

}

参考如何模拟新对象的构造

话虽如此,理想情况下目标类应该通过构造函数注入遵循显式依赖原则


public class ClassA {

    final ClassB objectOfB;


    public ClassA(ClassB objectOfB) {

        this.objectOfB = objectOfB;

    }


    public int add(int a, int b) {

        int addition = objectOfB.performCalculation(a,b);

        return addition;

    }

}

允许类显式地声明执行其设计功能所依赖的内容。


它还允许控制反转和松散耦合,这使得类更灵活地维护和测试


@RunWith(PowerMockRunner.class)

public class ClassATest {

    @Test

    public void testAddFromClassA() throws Exception {

        int expected = 15;

        ClassB objB = Mockito.mock(ClassB.class);

        Mockito.when(objB.performCalculation(5, 10)).thenReturn(expected);


        ClassA objA = new ClassA(objB);


        //Act

        int actual = objA.add(5, 10);


        //Assert

        assertEquals(expected, actual);

    }

}

仅仅因为 PowerMockito 允许模拟构造新对象并不意味着我们应该这样做。


如果遵循正确的设计原则,那么确实不需要这样的黑客攻击。


查看完整回答
反对 回复 2023-10-12
  • 1 回答
  • 0 关注
  • 60 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信