問題描述
我是新的 TestNG 和一般的單元測(cè)試.我將 TestNG 6.9.6 與 Mockito 1.10.19 和 PowerMock 1.6.4 一起使用.我想驗(yàn)證 MyService
類中的 myMethod()
方法是否在內(nèi)部使用正確的參數(shù)調(diào)用靜態(tài)方法 Util.myStaticMethod
.由于 Mockito 本身不支持對(duì)靜態(tài)方法的驗(yàn)證,因此我將 PowerMock 與它一起使用.我的測(cè)試類如下所示:
公共類 MyTest{私人的我的服務(wù)我的服務(wù);@Captor ArgumentCaptor<字符串>參數(shù)捕捉器;@BeforeMethod公共無(wú)效設(shè)置(){MockitoAnnotations.initMocks( 這個(gè) );我的服務(wù) = 新的我的服務(wù)();}@測(cè)試@PrepareForTest(MyService.class)公共無(wú)效我的測(cè)試(){PowerMockito.mockStatic(Util.class);myService.myMethod("arg");PowerMockito.verifyStatic(10);Util.myStaticMethod(anyString());}}
這個(gè)測(cè)試預(yù)計(jì)會(huì)失敗,因?yàn)?myMethod
只調(diào)用了一次靜態(tài)方法 Util.myStaticMethod()
.但是當(dāng)我運(yùn)行測(cè)試時(shí),它總是通過(guò),無(wú)論我將什么值傳遞給 PowerMockito.verifyStatic()
.
另外,如果我在這個(gè)類中編寫另一個(gè)測(cè)試方法然后運(yùn)行測(cè)試,我會(huì)得到以下錯(cuò)誤
org.mockito.exceptions.misusing.UnfinishedVerificationException:此處缺少驗(yàn)證(模擬)的方法調(diào)用:->在 mypackage.MyTest.myTest(MyTest.java:21)正確驗(yàn)證示例:驗(yàn)證(模擬).doSomething()此外,此錯(cuò)誤可能會(huì)出現(xiàn),因?yàn)槟?yàn)證了以下任一方法:final/private/equals()/hashCode() 方法.這些方法*不能*被存根/驗(yàn)證.不支持在非公共父類上聲明的模擬方法.在 mypackage.MyTest.myTest.setup(MyTest.java:10)結(jié)果 :失敗的測(cè)試:MyTest.setup:10 未完成驗(yàn)證缺少對(duì)版本的方法調(diào)用...測(cè)試運(yùn)行:3,失敗:1,錯(cuò)誤:0,跳過(guò):1
它在 verifyStatic()
方法處失敗,這讓我認(rèn)為 verifyStatic() 方法需要更多我沒有提供的東西.此外,它表示測(cè)試總數(shù)為 3,而在這種情況下,我只有兩種測(cè)試方法.
任何幫助將不勝感激.
按照建議,我嘗試將 MyUtil
類放在 @PrepareForTest
注釋中,它仍然給出相同的錯(cuò)誤.
好的,我認(rèn)為這是非常特定于 TestNG 配置的,因?yàn)樗?JUnit 示例都是開箱即用"的!
閱讀 PowerMock GitHub 站點(diǎn)上的 this 鏈接,該鏈接描述了有關(guān)如何將 TestNG 與 PowerMock 一起使用.使用此示例代碼在此處描述了您驗(yàn)證對(duì)模擬 static
方法的調(diào)用的場(chǎng)景:
@PrepareForTest(IdGenerator.class)公共類 MyTestClass {@測(cè)試公共無(wú)效demoStaticMethodMocking()拋出異常{模擬靜態(tài)(IdGenerator.class);when(IdGenerator.generateNewId()).thenReturn(2L);新的 ClassUnderTest().methodToTest();//可選地驗(yàn)證靜態(tài)方法是否被實(shí)際調(diào)用驗(yàn)證靜態(tài)();IdGenerator.generateNewId();}}
然后是這個(gè)信息塊:
<塊引用>為此,您需要告訴 TestNG 使用 PowerMock 對(duì)象工廠
這是使用 TestNG XML 配置或在測(cè)試代碼本身中完成的.為了完整起見,我已將上述 URL 中給出的選項(xiàng)復(fù)制到下方.FWIW 我擴(kuò)展了 PowerMockTestCase
并且驗(yàn)證按您的預(yù)期工作.
最后,不要忘記 @PrepareForTest
正確的類 - 即包含要模擬的 static
方法的類,正如@Bax 指出的那樣 這里.
作為進(jìn)一步的提示(您可能已經(jīng)知道,但無(wú)論如何這里值得一提),因?yàn)槟鷽]有使用 Mockito 來(lái)模擬對(duì)象,所以可以安全地刪除 MockitoAnnotations.initMocks(this)
.
完成所有這些工作后,您可能還想考慮是否使用 'Black Magic' 像 Powermock 這樣的工具實(shí)際上在您的設(shè)計(jì)中暴露了 代碼異味?特別是因?yàn)榭雌饋?lái)包含 static
方法的類在您的所有權(quán)之下.這意味著您可以使用不使用 static
的替代設(shè)計(jì).我強(qiáng)烈推薦 Michael Feathers 的書Working Effectively with Legacy Code,它可能會(huì)改變你的整個(gè)軟件設(shè)計(jì)和測(cè)試方法......
祝你好運(yùn)!
<塊引用>配置 TestNG 以使用 PowerMock 對(duì)象工廠
使用套件.xml
在您的 suite.xml 中,在套件標(biāo)簽中添加以下內(nèi)容:object-factory="org.powermock.modules.testng.PowerMockObjectFactory"
例如
<套件名稱="dgf" verbose="10"object-factory="org.powermock.modules.testng.PowerMockObjectFactory"><測(cè)試名稱="dgf"><類><類名="com.mycompany.Test1"/><類名="com.mycompany.Test2"/></類></測(cè)試>
如果您使用的是 Maven,您可能需要向 Surefire 指出該文件:
<插件><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><配置><suiteXmlFiles><suiteXmlFile>suite.xml</suiteXmlFile></suiteXmlFiles></配置></插件>
以編程方式
將這樣的方法添加到您的測(cè)試類中:
@ObjectFactory public IObjectFactory getObjectFactory() {返回新的 org.powermock.modules.testng.PowerMockObjectFactory();}
或者為了安全起見,您也可以從 PowerMockTestCase
進(jìn)行擴(kuò)展:
@PrepareForTest(IdGenerator.class)公共類 MyTestClass 擴(kuò)展 PowerMockTestCase { ... }
I am new TestNG and unit-testing in general. I am using TestNG 6.9.6 with Mockito 1.10.19 and PowerMock 1.6.4. I want to verify whether the myMethod()
method in MyService
class internally calls the static method Util.myStaticMethod
with the correct arguments. Since verification of static methods is not natively supported in Mockito, I am using PowerMock along with it. My Test class is shown below:
public class MyTest
{
private MyService myService;
@Captor ArgumentCaptor<String> argCaptor;
@BeforeMethod
public void setup()
{
MockitoAnnotations.initMocks( this );
myService = new MyService();
}
@Test
@PrepareForTest(MyService.class)
public void myTest()
{
PowerMockito.mockStatic(Util.class);
myService.myMethod("arg");
PowerMockito.verifyStatic(10);
Util.myStaticMethod(anyString());
}
}
This test is expected to fail, as myMethod
calls the static method Util.myStaticMethod()
only once. But when i run the test, it always passes, no matter what value i pass to PowerMockito.verifyStatic()
.
Also, if I write another test method in this class and then run the test, I get the following error
org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-> at mypackage.MyTest.myTest(MyTest.java:21)
Example of correct verification:
verify(mock).doSomething()
Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
at mypackage.MyTest.myTest.setup(MyTest.java:10)
Results :
Failed tests:
MyTest.setup:10 UnfinishedVerification
Missing method call for ver...
Tests run: 3, Failures: 1, Errors: 0, Skipped: 1
It fails at the verifyStatic()
method, which makes me think that the verifyStatic() method needs something more that i am not providing. Also, it indicates the total number of tests as 3 whereas in this case I have only two test methods.
Any help would be appreciated.
EDIT : As suggested, I tried putting MyUtil
class in the the @PrepareForTest
annotation, it still gives the same error.
OK, I think this is very specific to TestNG configurations, since all of the JUnit examples work 'out of the box'!
Read through this link from the PowerMock GitHub site which describes further detail on how to use TestNG together with PowerMock. Exactly your scenario of verifying calls to mocked static
methods is described there using this example code:
@PrepareForTest(IdGenerator.class) public class MyTestClass { @Test public void demoStaticMethodMocking() throws Exception { mockStatic(IdGenerator.class); when(IdGenerator.generateNewId()).thenReturn(2L); new ClassUnderTest().methodToTest(); // Optionally verify that the static method was actually called verifyStatic(); IdGenerator.generateNewId(); } }
Which is then followed by this nugget of information:
For this to work you need to tell TestNG to use the PowerMock object factory
This is done using either TestNG XML config, or in the test's code itself. For completeness I've copied below the options given at the above URL. FWIW I extended PowerMockTestCase
and the verification worked as you expect.
Finally, don't forget to @PrepareForTest
the correct class - i.e. the class containing the static
methods which you want to mock, as @Bax pointed out here.
As a further hint (which you probably already know about, but worth mentioning here anyway) since you aren't using Mockito to mock objects, MockitoAnnotations.initMocks(this)
can be safely deleted.
Once you've got all this working, you might also like to consider whether the use of 'Black Magic' tools like Powermock is actually exposing code smells in your design? Especially since it looks like the classes containing static
methods are under your ownership. This means you could use an alternative design that doesn't use static
s. I highly recommend Michael Feathers' book Working Effectively with Legacy Code, it might just change your whole approach to software design and testing...
Good luck!
Configure TestNG to use the PowerMock object factory
Using suite.xml
In your suite.xml add the following in the suite tag:
object-factory="org.powermock.modules.testng.PowerMockObjectFactory"
e.g.<suite name="dgf" verbose="10" object-factory="org.powermock.modules.testng.PowerMockObjectFactory"> <test name="dgf"> <classes> <class name="com.mycompany.Test1"/> <class name="com.mycompany.Test2"/> </classes> </test>
If you're using Maven you may need to point out the file to Surefire:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <suiteXmlFiles> <suiteXmlFile>suite.xml</suiteXmlFile> </suiteXmlFiles> </configuration> </plugin>
Programmatically
Add a method like this to your test class:
@ObjectFactory public IObjectFactory getObjectFactory() { return new org.powermock.modules.testng.PowerMockObjectFactory(); }
or to be on the safe side you can also extend from the
PowerMockTestCase
:@PrepareForTest(IdGenerator.class) public class MyTestClass extends PowerMockTestCase { ... }
這篇關(guān)于TestNG + Mockito + PowerMock - verifyStatic() 不起作用的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!