假设我有以下课程
public class StaticClass {
public static void staticMethod() throws SomeException {
System.out.println("staticMethod");
}
private StaticClass() {
}
}
和
public class SomeClass {
public void someMethod() {
try {
StaticClass.staticMethod();
}catch(SomeException ex) {
System.out.println("SomeException occurred");
return;
}
System.out.println("SomeException didn't occur");
}
}
我正在使用
进行测试@RunWith(PowerMockRunner.class)
@PrepareForTest(StaticClass.class)
public class SomeClassTest {
@Test
public void testStaticMethod() throws Exception {
mockStatic(StaticClass.class);
doThrow(new SomeException("unimportant message")).when(StaticClass.class,
"staticMethod");
//test something where exception is needed
SomeClass instance = new SomeClass();
try {
instance.someMethod();
fail("IllegalStateException expected");
}catch(IllegalStateException expected) {
}
//now test something where exception isn't needed
instance.someMethod();
}
}
如何撤消静态模拟/配置以抛出SomeException
,以便我可以在第二个instance.someMethod()
中的try-catch块之后测试代码?
PowerMock: How to unmock a method?不适用,因为没有模拟引用传递给Mockito.reset
并传递StaticClass
会导致java.lang.ClassCastException: java.lang.Class cannot be cast to org.mockito.internal.creation.bytebuddy.MockAccess
。
SomeException
只是扩展Exception
。
SSCCE在https://gitlab.com/krichter/powermock-undo-statik-mocking提供。
我正在使用PowerMock 1.7.3。
答案 0 :(得分:2)
我的意见,但一般来说,单元测试应该使用单一的代码路径。 (我认为这是对测试方法应用单一责任。)
我的关于拆分测试的建议确实解决了这个问题。我不知道细节,但@PrepareForTest为每个测试提供了一个新的StaticClass 。
这些单独的测试有效:
@Test
public void testStaticMethodWhenSomethingUnexpectedHappens() throws Exception {
mockStatic(StaticClass.class);
// changed exception type
doThrow(new IllegalStateException("unimportant message")).when(StaticClass.class, "staticMethod");
SomeClass instance = new SomeClass();
try {
instance.someMethod();
fail("IllegalStateException expected");
} catch (IllegalStateException expected) {
}
// added verification
verifyStaticMethodWasInvokedOneTime();
}
@Test
public void testStaticMethodHappyPath() throws Exception {
mockStatic(StaticClass.class);
doNothing().when(StaticClass.class, "staticMethod");
SomeClass instance = new SomeClass();
instance.someMethod();
// added verification
verifyStaticMethodWasInvokedOneTime();
}
private void verifyStaticMethodWasInvokedOneTime() throws SomeException {
verifyStatic(StaticClass.class);
StaticClass.staticMethod();
}
答案 1 :(得分:0)
对于任何想知道如何重置PowerMocks e.x的人。对于那些讨厌的私人静态最终记录器...
有一个issue(请参见接受的解决方案中的Karl的注释)来解决这个问题,解决方案是在方法级别使用@PrepareForTest。
因此在您的测试方法中,您需要注释
<div class="booking_form_request
<?php
if($wpestate_options['sidebar_class']=='' || $wpestate_options['sidebar_class']=='none' ){
print ' col-md-4 ';
}else{
print esc_attr($wpestate_options['sidebar_class']);
}
?>
" id="booking_form_request">
<div id="booking_form_request_mess"></div>
<h3 ><?php esc_html_e('Book Now','wprentals');?></h3>
<div class="has_calendar calendar_icon">
<input type="text" id="start_date" placeholder="<?php echo wpestate_show_labels('check_in',$rental_type); ?>" class="form-control calendar_icon" size="40" name="start_date"
value="<?php if( isset($_GET['check_in_prop']) ){
echo sanitize_text_field ( $_GET['check_in_prop'] );
}
?>">
</div>
<div class=" has_calendar calendar_icon">
<input type="text" id="end_date" disabled placeholder="<?php echo wpestate_show_labels('check_out',$rental_type); ?>" class="form-control calendar_icon" size="40" name="end_date"
value="<?php if( isset($_GET['check_out_prop']) ){
echo sanitize_text_field ( $_GET['check_out_prop'] );
}
?>">
</div>
<?php
$max_guest = get_post_meta($post_id,'guest_no',true);
if($rental_type==0){
?>
<div class=" has_calendar guest_icon ">
<?php
print '
<div class="dropdown form-control">
<div data-toggle="dropdown" id="booking_guest_no_wrapper" class="filter_menu_trigger" data-value="';
if(isset($_GET['guest_no_prop']) && $_GET['guest_no_prop']!=''){
echo esc_html( $_GET['guest_no_prop'] );
}else{
echo 'all';
}
print '">';
print '<div class="text_selection">';
if(isset($_GET['guest_no_prop']) && $_GET['guest_no_prop']!=''){
echo esc_html( $_GET['guest_no_prop'] ).' '.esc_html__( 'guests','wprentals');
}else{
esc_html_e('Guests','wprentals');
}
print '</div>';
print '<span class="caret caret_filter"></span>
</div>
<input type="hidden" name="booking_guest_no" value="">
<ul class="dropdown-menu filter_menu" role="menu" aria-labelledby="booking_guest_no_wrapper" id="booking_guest_no_wrapper_list">
'.$guest_list.'
</ul>
</div>';//escaped above
?>
</div>
<?php
}else{
?>
<input type="hidden" name="booking_guest_no" value="1">
<?php
}
// shw extra options
wpestate_show_extra_options_booking($post_id)
?>
<p class="full_form " id="add_costs_here"></p>
<input type="hidden" id="listing_edit" name="listing_edit" value="<?php print intval($post_id);?>" />
<?php wpestate_show_booking_button($post_id);?>
<div class="third-form-wrapper">
<div class="col-md-6 reservation_buttons">
<div id="add_favorites" class=" <?php print esc_attr($favorite_class);?>" data-postid="<?php esc_attr(the_ID());?>">
<?php print trim($favorite_text);?>
</div>
</div>
<div class="col-md-6 reservation_buttons">
<div id="contact_host" class="col-md-6" data-postid="<?php esc_attr(the_ID());?>">
<?php esc_html_e('Contact Owner','wprentals');?>
</div>
</div>
</div>
<?php
echo wpestate_share_unit_desing($post_id);
?>
</div>
</div>
</div>
如果您想重置每个方法,只需将@PrepareForTest装饰器放在类而不是方法上