單元測(cè)試主要是關(guān)于測(cè)試您的代碼,而僅是在有限范圍內(nèi)的代碼??紤]到 Shiro 時(shí),您 true 要關(guān)注的是您的代碼可以與 Shiro 的* API *一起正常工作-您并不需要測(cè)試 Shiro 的實(shí)現(xiàn)是否正常工作(這是 Shiro 開發(fā)團(tuán)隊(duì)必須確保的事情)在 Shiro 的代碼庫(kù)中)。
檢驗(yàn) Shiro 的實(shí)現(xiàn)是否可以與您的實(shí)現(xiàn)一起工作的測(cè)試實(shí)際上是集成測(cè)試(下面討論)。
因?yàn)閱卧獪y(cè)試更適合測(cè)試您自己的邏輯(而不是您的邏輯可能調(diào)用的任何實(shí)現(xiàn)),所以“模擬”您邏輯所依賴的任何 API 是一個(gè)好主意。這在 Shiro 上非常有效-您可以模擬?Subject
?接口,并使其反映您希望被測(cè)代碼對(duì)之做出反應(yīng)的任何條件。我們可以利用諸如EasyMock和Mockito之類的現(xiàn)代模擬框架為我們完成此任務(wù)。
但是如上所述,Shiro 測(cè)試中的關(guān)鍵是要記住在測(cè)試執(zhí)行期間必須將任何 Subject 實(shí)例(模擬或真實(shí))綁定到線程。因此,我們要做的就是綁定模擬主題,以確保事情按預(yù)期進(jìn)行。
(此示例使用 EasyMock,但 Mockito 的效果也一樣):
import org.apache.shiro.subject.Subject;
import org.junit.After;
import org.junit.Test;
import static org.easymock.EasyMock.*;
/**
* Simple example test class showing how one may perform unit tests for
* code that requires Shiro APIs.
*/
public class ExampleShiroUnitTest extends AbstractShiroTest {
@Test
public void testSimple() {
//1. Create a mock authenticated Subject instance for the test to run:
Subject subjectUnderTest = createNiceMock(Subject.class);
expect(subjectUnderTest.isAuthenticated()).andReturn(true);
//2. Bind the subject to the current thread:
setSubject(subjectUnderTest);
//perform test logic here. Any call to
//SecurityUtils.getSubject() directly (or nested in the
//call stack) will work properly.
}
@After
public void tearDownSubject() {
//3. Unbind the subject from the current thread:
clearSubject();
}
}
如您所見,我們沒有設(shè)置 Shiro ?SecurityManager
?實(shí)例或配置?Realm
?或類似的東西。我們只是在創(chuàng)建一個(gè)模擬?Subject
?實(shí)例,并通過?setSubject
?方法調(diào)用將其綁定到線程。這樣可以確保測(cè)試代碼或我們正在測(cè)試的?SecurityUtils.getSubject()
?代碼中的所有調(diào)用均能正常工作。
請(qǐng)注意,?setSubject
?方法實(shí)現(xiàn)會(huì)將您的模擬 Subject 綁定到線程,并且將保留在那里,直到您使用其他?Subject
?實(shí)例調(diào)用?setSubject
?或通過?clearSubject()
?調(diào)用從線程中明確清除它為止。
保持主題與線程綁定多長(zhǎng)時(shí)間(或?qū)⑵涮鎿Q為其他測(cè)試中的新實(shí)例)取決于您和您的測(cè)試要求。
該示例中的?tearDownSubject()
?方法使用 Junit 4 注解,以確保無論執(zhí)行哪種測(cè)試方法,在執(zhí)行線程后都會(huì)從線程中清除 Subject。這要求您設(shè)置一個(gè)新的?Subject
?實(shí)例,并為每個(gè)執(zhí)行的測(cè)試(通過?setSubject
?)進(jìn)行設(shè)置。
但是,這并非絕對(duì)必要。例如,您可以在每個(gè)測(cè)試的開始(例如,以?@Before
?Comments 的方法)(通過setSujbect)綁定一個(gè)新的 ?Subject
? 實(shí)例。但是,如果要執(zhí)行此操作,則最好使用?@After tearDownSubject()
?方法保持事物對(duì)稱和“干凈”。
您可以在每種方法中手動(dòng)混合和匹配此設(shè)置/拆卸邏輯,或者使用@Before 和@AfterComments(如果您認(rèn)為合適)。但是,由于所有測(cè)試中的tearDownShiro()方法中都有?@AfterClass
?注解,因此?AbstractShiroTest
?超類將在所有測(cè)試后將其從線程中解除綁定。
更多建議: