1

我有一個基類,它看起來是這樣的:如何嘲笑和驗證ScheduledExcecutorService的方法被調用子類

public abstract class BaseClass implements Runnable { 
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 

@Override 
public void run() { 
    someFunction(); 
} 
protected abstract void someFunction(); 
} 

然後,我有一個子類是這樣的:

public class ChildClass extends BaseClass { 
functionNeedsToBeTested() { 
    scheduler.scheduleAtFixedRate(this, 0L, 5L, TimeUnit.HOURS) 
} 
someFunction() { 
    //Does Something 
} 
} 

現在問題來了,當我嘗試寫測試時,我無法驗證scheduleAtFixedRate方法的調用。我的測試是這樣的:

@RunWith(MockitoJUnitRunner.class) 
public class TestClass { 
@Mock 
private ScheduledExecutorService scheduler; 

@InjectMocks 
private ChildClass obj; 

@Test 
public void testFunc() { 
    obj.functionNeedsToBeTested(); 
    Mockito.verify(scheduler).scheduleAtFixedRate(Mockito.any(ChildClass.class, Mockito.anyLong(), Mockito.anyLong(), Mockito.any(TimeUnit.class))); 
} 
} 

測試給了我這個錯誤:

junit.framework.AssertionFailedError: 
    Wanted but not invoked: 
    scheduler.scheduleAtFixedRate(
     <any>, 
     <any>, 
     <any>, 
     <any> 
    ); 

回答

3

在您的測試中,創造了一個模擬調度,但它沒有被測試的對象。

如果您注入調度程序,則可以使該方法可測試,而不是在基類中實例化該方法。您可能需要調度程序作爲BaseClass構造函數的參數,例如

+0

感謝它以這種方式工作,但我想知道是否有方法來測試此準確的代碼而無需修改代碼並只修改測試! ! –

+0

@ManthanJamdagni我想你可以使用反射來代替執行者使用反射,用https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible(java.lang .reflect.AccessibleObject [],%20boolean)否決它是最終的。然而,注入執行程序而不是使用硬編碼的可以說是一種更好的設計,因爲您的BaseClass現在可以與任何給定的執行程序一起工作。有關詳細說明,請參閱https://en.m.wikipedia.org/wiki/Dependency_inversion_principle – CrimsonCricket