使用Powermock在Groovy中模拟instanse创建

时间:2017-07-11 17:49:34

标签: unit-testing groovy mockito testng powermock

我试图通过带有Powermock(1.7.0RC2),Mockito2(2.4.0)和TestNG(6.8.21)的Groovy类中的new运算符来模拟实例创建。但通常的方法是行不通的。这是我的课程和考试。

public class A {
    public String send() {
        B b = new B();
        return b.send();
    }
}    

public class B {       
    public String send() {
        return "SendFromOriginB";
    }
}

@PrepareForTest([A.class])
class TestConstructor extends PowerMockTestCase {
    @Mock
    private B bMock

    @Test
    void test() {
      A a = new A()

     given(bMock.send()).willReturn("Send from B mock")
     PowerMockito.whenNew(B.class).withNoArguments().thenReturn(bMock)
     assertEquals(a.send(), "Send from B mock")
    }
}

问题是A类是 Groovy类。似乎 Powermock.whenNew 并不知道新B()正在调用。

因此, var b 包含B类的常用实例,而不是 mock ,并且测试失败。但是,如果A类是 Java类,则测试按预期工作, var b 包含我的模拟。 Groovy通过自己的方式创建实例,我无法正确地模拟它们。

有没有人知道如何在Groovy类中模拟实例创建?

2 个答案:

答案 0 :(得分:0)

你明白Groovy不是Java吗?是什么让您认为适用于Java语言的构造适用于其他语言?

从这个意义上讲:您的第一步应该是使用javap检查由Groovy为A类创建的文件。看看那里有什么

除此之外:用工厂替换<html> <head> <script src="\node_modules\jquery\dist\jquery.js"></script> <script src="node_modules\adal-angular\lib\adal.js"></script> </head> <body> <button id="login"> login</button> <button id="clickMe">click me</button> <script> $(function () { var endpoints = { "https://graph.microsoft.com": "https://graph.microsoft.com" }; window.config = { tenant: 'xxxx.onmicrosoft.com', clientId: 'xxxxxxxxxxxxxxxxx', endpoints: endpoints }; window.authContext = new AuthenticationContext(config); $("#login").click(function () { window.authContext.login(); }); $("#clickMe").click(function () { var user = window.authContext.getCachedUser(); console.log(user); window.authContext.acquireToken('https://graph.microsoft.com', function (error, token) { console.log(error); console.log(token); $.ajax({ url: 'https://graph.microsoft.com/v1.0/me/', headers:{'authorization':'Bearer '+ token}, type:'GET', dataType:'json' }).done(function(res) { console.log(res['userPrincipalName']); }); }); } ); function init(){ if(window.location.hash!="") window.authContext.handleWindowCallback(window.location.hash); } init(); }); </script> </body> </html> 并允许注入该工厂允许您轻松测试,您甚至不需要PowerMock

答案 1 :(得分:0)

我有两个建议!

使用@CompileStatic

@CompileStatic // <- you can use on class level
public class A {

    // Or you can use on method level 
    // depending on groovy version
    @CompileStatic
    public String send() {
        // 
    }
}

此注释将删除打破PowerMock.whenNew()方法的元编程协议。

我的第二个建议是使用Spock Framework!这个框架基于BDD,当你使用groovy时,你的测试代码非常干净和可读! Spock也可以mock constructor

spock中的测试代码可能是这样的:

def "Given an class A, when B constructor returns a mock, a must use the mock"() {
    given:
    String sendFromBMock = "Send from B mock"
    and:
    bMock.send() >> sendFromBMock
    when:
    new B() >> bMock
    then:
    a.send() == sendFromBMock
}