問題描述
我是新的 TestNG 和一般的單元測試.我將 TestNG 6.9.6 與 Mockito 1.10.19 和 PowerMock 1.6.4 一起使用.我想驗證 MyService
類中的 myMethod()
方法是否在內部使用正確的參數調用靜態方法 Util.myStaticMethod
.由于 Mockito 本身不支持對靜態方法的驗證,因此我將 PowerMock 與它一起使用.我的測試類如下所示:
公共類 MyTest{私人的我的服務我的服務;@Captor ArgumentCaptor<字符串>參數捕捉器;@BeforeMethod公共無效設置(){MockitoAnnotations.initMocks( 這個 );我的服務 = 新的我的服務();}@測試@PrepareForTest(MyService.class)公共無效我的測試(){PowerMockito.mockStatic(Util.class);myService.myMethod("arg");PowerMockito.verifyStatic(10);Util.myStaticMethod(anyString());}}
這個測試預計會失敗,因為 myMethod
只調用了一次靜態方法 Util.myStaticMethod()
.但是當我運行測試時,它總是通過,無論我將什么值傳遞給 PowerMockito.verifyStatic()
.
另外,如果我在這個類中編寫另一個測試方法然后運行測試,我會得到以下錯誤
org.mockito.exceptions.misusing.UnfinishedVerificationException:此處缺少驗證(模擬)的方法調用:->在 mypackage.MyTest.myTest(MyTest.java:21)正確驗證示例:驗證(模擬).doSomething()此外,此錯誤可能會出現,因為您驗證了以下任一方法:final/private/equals()/hashCode() 方法.這些方法*不能*被存根/驗證.不支持在非公共父類上聲明的模擬方法.在 mypackage.MyTest.myTest.setup(MyTest.java:10)結果 :失敗的測試:MyTest.setup:10 未完成驗證缺少對版本的方法調用...測試運行:3,失敗:1,錯誤:0,跳過:1
它在 verifyStatic()
方法處失敗,這讓我認為 verifyStatic() 方法需要更多我沒有提供的東西.此外,它表示測試總數為 3,而在這種情況下,我只有兩種測試方法.
任何幫助將不勝感激.
按照建議,我嘗試將 MyUtil
類放在 @PrepareForTest
注釋中,它仍然給出相同的錯誤.
好的,我認為這是非常特定于 TestNG 配置的,因為所有 JUnit 示例都是開箱即用"的!
閱讀 PowerMock GitHub 站點上的 this 鏈接,該鏈接描述了有關如何將 TestNG 與 PowerMock 一起使用.使用此示例代碼在此處描述了您驗證對模擬 static
方法的調用的場景:
@PrepareForTest(IdGenerator.class)公共類 MyTestClass {@測試公共無效demoStaticMethodMocking()拋出異常{模擬靜態(IdGenerator.class);when(IdGenerator.generateNewId()).thenReturn(2L);新的 ClassUnderTest().methodToTest();//可選地驗證靜態方法是否被實際調用驗證靜態();IdGenerator.generateNewId();}}
然后是這個信息塊:
<塊引用>為此,您需要告訴 TestNG 使用 PowerMock 對象工廠
這是使用 TestNG XML 配置或在測試代碼本身中完成的.為了完整起見,我已將上述 URL 中給出的選項復制到下方.FWIW 我擴展了 PowerMockTestCase
并且驗證按您的預期工作.
最后,不要忘記 @PrepareForTest
正確的類 - 即包含要模擬的 static
方法的類,正如@Bax 指出的那樣 這里.
作為進一步的提示(您可能已經知道,但無論如何這里值得一提),因為您沒有使用 Mockito 來模擬對象,所以可以安全地刪除 MockitoAnnotations.initMocks(this)
.
完成所有這些工作后,您可能還想考慮是否使用 'Black Magic' 像 Powermock 這樣的工具實際上在您的設計中暴露了 代碼異味?特別是因為看起來包含 static
方法的類在您的所有權之下.這意味著您可以使用不使用 static
的替代設計.我強烈推薦 Michael Feathers 的書Working Effectively with Legacy Code,它可能會改變你的整個軟件設計和測試方法......
祝你好運!
<塊引用>配置 TestNG 以使用 PowerMock 對象工廠
使用套件.xml
在您的 suite.xml 中,在套件標簽中添加以下內容:object-factory="org.powermock.modules.testng.PowerMockObjectFactory"
例如
<套件名稱="dgf" verbose="10"object-factory="org.powermock.modules.testng.PowerMockObjectFactory"><測試名稱="dgf"><類><類名="com.mycompany.Test1"/><類名="com.mycompany.Test2"/></類></測試>
如果您使用的是 Maven,您可能需要向 Surefire 指出該文件:
<插件><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><配置><suiteXmlFiles><suiteXmlFile>suite.xml</suiteXmlFile></suiteXmlFiles></配置></插件>
以編程方式
將這樣的方法添加到您的測試類中:
@ObjectFactory public IObjectFactory getObjectFactory() {返回新的 org.powermock.modules.testng.PowerMockObjectFactory();}
或者為了安全起見,您也可以從 PowerMockTestCase
進行擴展:
@PrepareForTest(IdGenerator.class)公共類 MyTestClass 擴展 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 { ... }
這篇關于TestNG + Mockito + PowerMock - verifyStatic() 不起作用的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!