【问题标题】:EasyMock + PowerMock : How to mock field?EasyMock + PowerMock:如何模拟字段?
【发布时间】:2014-02-17 12:33:14
【问题描述】:

让我们看看这段代码:

    public class A {

        public void doSmth() {  // pay attention - void method
           // impl
        }
    }

    public class B {
       private A a_instance; // null

       public void doSmthElse() {
          a_instance.doSmth(); // NPE here without mock
          // also do smth. else
       }
    }

现在,我有 B b = new B(); 并且我想测试 b.doSmthElse() ,但我需要先为 a_instance 对象创建一个模拟,否则我会得到 NullPointerException !我如何使用 EasyMock 或 PowerMock 来实现这一点???

【问题讨论】:

  • 你试过什么?你在使用依赖注入库或框架吗?
  • 什么意思?是的,在现实生活中,a_instance 对象被注入那里,但对于单元测试,我需要模拟它。

标签: java unit-testing testng easymock powermock


【解决方案1】:
@Test
public void testDoSomething()
    {
    // setup: sut
    B b = new B();
    A mockA = EasyMock.createMock(A.class);
    b.setA_instance(mockA); // If you have a setter

    // setup: expectations
    mockA.doSmth();

    // exercise
    EasyMock.replay(mockA);
    b.doSmthElse();

    // verify
    EasyMock.verify(mockA);
    }

@Test
public void testDoSomething_setUsingReflection()
    {
    // setup: sut
    B b = new B();
    A mockA = EasyMock.createMock(A.class);
    // Set the collaborator using a Spring reflection utility
    ReflectionTestUtils.setField(b, "a_instance", mockA);

    // setup: expectations
    mockA.doSmth();

    // exercise
    EasyMock.replay(mockA);
    b.doSmthElse();

    // verify
    EasyMock.verify(mockA);
    }

【讨论】:

  • 然后我需要为 a_instance 设置 setter(我的意思是 setter 方法),我将仅用于测试目的。让代码仅用于包含一些业务逻辑的类中的测试并不是一个很好的做法。
  • 这是一个不同的问题,有许多不同的解决方案。您可以公开协作者,使用反射来设置它或使用像 Spring 的 ReflectionTestUtils 这样的实用程序。
  • 不,反射不起作用,因为我使用 EasyMock 为 B 类创建模拟,这就是为什么如果我尝试使用反射获取该字段,我会得到 NoSuchFieldException,因为我不知道这是怎么回事创建模拟时调用字段。
  • 你不需要使用 EasyMock 来创建 B 实例(这是你的 sut),只需要创建 A 模拟。如果您没有公共设置器,则确实意味着您正在使用框架来注入 a 实例,并且 fwk 肯定会使用反射。然后,您还必须在测试中使用反射。我会更新我的答案。
【解决方案2】:

你可以使用

instanceName.methodName();
Easymock.expectLastCall(); //for void methods this is how it is done

instanceName 可以是 mocked 或 actualInstance。

如果你可以将方法设为静态,那么使用 powermock 会更容易

Powermock.mockStatic(ClassNameContainingStaticMethod)

所有静态方法都被直接模拟

注意事项:- 将方法转换为静态方法可能会在其他部分出现问题。请谨慎操作

希望对您有所帮助。 万事如意!

【讨论】:

  • Easymock.expectLastCall(); 不是必需的。
【解决方案3】:

我看不出这里需要 PowerMock 的原因。您可以使用 EasyMock 本身来实现。

@Test
public void testDoSmthElse() {
    A a = EasyMock.createMock(A.class);
    EasyMock.expect(a.doSmth()).andReturn(/*some value */);
    EasyMock.replay(a);

    B b = new B();
    Object whatever = b.doSmthElse();

    assert(); // psuedo-line. Add whatever assertion required
}

注意:导入适当的类

【讨论】:

  • 将该行简单地替换为a.doSmth();,测试将通过。
  • 你需要在调用 b.doSmthElse() 之前将对象 A 注入到 B 中
猜你喜欢
  • 1970-01-01
  • 2014-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多