簡體   English   中英

如何使用powerMock在同一個類中模擬靜態和非靜態方法?

[英]How to mock both static and non static methods in a same class using powerMock?

我有一個簡單的案例來說明一個更復雜的案例(哦遺產代碼,我愛你,吟游詩人會以你的名義唱出奇妙的歌曲)。

想象一組類如下:

  • 實用類:
package org.osef.test;

public final class A {

    private static A instance;
    public static String status;

    private A() {
        initPaths();
    }

    public static A getInstance(){
            if(instance==null){
                instance = new A();
            }
            return instance;
    }

    private void initPaths() {
        A.status = "I have been in the method !";
    }
    public String doStuff() {
        return "stuff done ...";
    }
}
  • 叫它的班級
package org.osef.test;

public class B {

    public String doBdo() {
        A instance = A.getInstance();
        return instance.doStuff();
    }
}
  • 這一課測試了這一堆......咳嗽......非常難以理解的“邏輯”。

包org.osef.test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ A.class })
public class BTest {

    @Before
    public void setUp() {
        PowerMock.replace(PowerMock.method(A.class, "getInstance")).with(PowerMock.method(BTest.class, "giveOutInstance"));

        A a = A.getInstance();

        EasyMock.expect(a.doStuff()).andReturn("lol");
        EasyMock.replay(a);
    }

    @Test
    public void testDoBdo() {

        B b = new B();
        assertEquals("lol", b.doBdo());
        assertNull(A.status);
    }

    public static A giveOutInstance(){
        return Whitebox.newInstance(A.class);
    }
}
  • 另一種方法如下:
package org.osef.test;

//[imports ommited here but are the same that those of the previous example]

@RunWith(PowerMockRunner.class)
@PrepareForTest({ A.class })
public class BTest {

    @Before
    public void setUp() {
        PowerMock.mockStatic(A.class);
        A a = Whitebox.newInstance(A.class);
        EasyMock.expect(A.getInstance()).andReturn(a);
        PowerMock.replay(A.class);

        EasyMock.expect(a.doStuff()).andReturn("lol");

        EasyMock.replay(a);
    }

    @Test
    public void testDoBdo() {

        B b = new B();
        assertEquals("lol", b.doBdo());
        assertNull(A.status);
    }

}

但在所有情況下,我得到:

java.lang.IllegalStateException:沒有最后一次調用org.easymock.EasyMock.getControlForLastCall(EasyMock.java:560)上的org.easymock.EasyMock.expect(EasyMock.java:538)org.osef.test上提供的模擬。 BTest.setUp(BTest.java:25)......

  • 我只需要測試最后的A類。
  • 我需要避免它的構造函數邏輯(在我對doStuff“方法的測試中表現得很糟糕和無關緊要)。
  • 我必須測試doStuff。

知道如何有效地做我想做的事嗎?

我認為你的問題是你沒有重播類,你只是在每個測試中重放A的模擬實例。

PowerMock.replayAll()在這里是你的朋友。 它將強制您期望的類處於重放模式,然后可以通過調用靜態方法返回您的模擬實例。

以下是我為您的示例生成的示例測試:

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.easymock.EasyMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class BTest{

    @Test
    public void thatCallingClassMakesExpectedCalls() {
        final A mockA = PowerMock.createMock(A.class);
        EasyMock.expect(mockA.doStuff()).andReturn("lol").anyTimes();

        PowerMock.mockStatic(A.class);
        EasyMock.expect(A.getInstance()).andReturn(mockA).anyTimes();

        PowerMock.replayAll(mockA);

        final B callingClass = new B();
        final String doBdo = callingClass.doBdo();
        assertThat(doBdo, is("lol"));

        EasyMock.verify(mockA);
        PowerMock.verifyAll();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM