2011-09-15 37 views
10

我有一起運行的集成測試(加載上下文)和單元測試。我的代碼不會使用spring來編譯時間。在單元測試運行期間禁用某些方面

我的問題是,我聲明的建議也運行在我的一些單元測試。這殺死了單元測試的概念,這就是爲什麼我想禁用它們的原因。

有什麼我可以把切入點聲明,我可以調用一些方法,一些春季配置,或maven命令,禁用這些建議的東西像所有* UnitTest.java?

感謝您的幫助。


例如:

我有以下單元測試:

@RunWith(MockitoJUnitRunner.class) 
public class CompanyServiceImplTest { 
    @Test 
    public void createCampaignTest() throws Exception { 
     when(companyDaoMock.saveCompany(any(Campaign.class))).thenReturn(77L); 

     Long campaignId = companyService.createCampaign(campaignMock); 

     assertEquals(Long.valueOf(77L), Long.valueOf(campaignId)); 
    } 
} 

和以下服務方法:

@Override 
@Transactional 
@EventJournal(type = EventType.CAMPAIGN_CREATE, owner = EventOwner.TERMINAL_USER) 
public Long createCampaign(Campaign campaign) { 
    return companyDao.saveCompany(campaign); 
} 

方面:

@Aspect 
public class EventJournalAspect { 

    @Autowired 
    private EventJournalService eventJournalService; 

    @Pointcut(value="execution(public * *(..))") 
    public void anyPublicMethod() {} 

    @Pointcut("within(com.terminal.service..*)") 
    private void inService() {} 

    @AfterReturning(pointcut = "anyPublicMethod() && inService() && @annotation(eventJournal) && args(entity,..)", returning = "id") 
    public void process(Object id, EventJournal eventJournal, AbstractDomainEntity entity) 
      throws Throwable { 
     if (eventJournal.type() != EventType.CAMPAIGN_PAYMENT || id != null) { 
      saveEvent(eventJournal, EventStatus.SUCCESS, entity, (Long) id); 
     } 
    } 

    @AfterThrowing(pointcut = "anyPublicMethod() && inService() && @annotation(eventJournal) && args(entity,..)", throwing="ex") 
    public void processException(EventJournal eventJournal, AbstractDomainEntity entity, Exception ex) throws Throwable { 
     saveEvent(eventJournal, EventStatus.FAILURE, entity, null); 
    } 

    private void saveEvent(EventJournal eventJournal, EventStatus status, AbstractDomainEntity entity, Long persistentId) { 
     EventType type = eventJournal.type(); 
     EventOwner owner = eventJournal.owner(); 
     eventJournalService.saveEvent(type, owner, EventStatus.SUCCESS, entity, persistentId); 
    } 

} 

測試執行時 - eventJournalService爲空。因此,我看到NullPointerException

回答

0

我只能猜測: 的第一件事情是有一個單獨的Spring的ApplicationContext-的test.xml, ,沒有成分掃描; 在maven中,您可以添加一個階段運行時間,不包括編織罐以進行測試。

0

編譯時織入會嵌入由您擁有的切入點標識的目標方法中的通知調用。我個人認爲在編譯時編織單元測試是很好的,因爲在運行時,你的單元確實包含內置建議的類。

我不想包含建議的想法是有兩個不同的編譯目標,一個編譯時編織,一個沒有,你應該能夠通過maven配置文件,一個dev配置文件不編織建議和一個prod配置文件編織方面英寸

3

答案很簡單:您想要使用if() pointcut expression


更新(這個問題也得到了更新後):上面的最初提供的鏈接應包含足夠的信息,但它是值得的,一個簡短的說明和簡單的例子:

if() pointcut是一個static方面方法返回boolean。如果返回值爲true,則表示像myPointcut() && if()這樣的任何組合切入點匹配,只要myPointcut()匹配。對於返回值false,整個組合切入點不匹配,從而有效地停用與切入點相連的任何建議。

那麼你可以在靜態if()切入點做什麼?

  • 評估一些工具類像TestMode.ACTIVE的靜態布爾成員,其在單元或集成測試是唯一真正的
  • 評估其測試過程中只設置
  • 評估Java系統屬性裏面只有一個環境變量測試
  • 期間設置,還有更多的東西

如果你想要做的事愛好者(和麻煩)和性能就不那麼重要了,你ç還會嘗試動態確定自動連接的方面成員變量是否等於null,並且只有在注入的對象實際存在時才激活您的切入點。這裏唯一的問題是如何從靜態方法中確定成員變量。我對Spring AOP一無所知,但在普通的AspectJ中有幫助類Aspects,它有幾個重載的方法,名爲aspectOf(..)。假設您的方面實例化爲單,你可以做這樣的事情:

@Pointcut("if()") 
public static boolean isActive() { 
    return Aspects.aspectOf(PerformanceMonitorAspect.class).eventJournalService != null; 
} 

// ... 

@AfterReturning(pointcut = "isActive() && anyPublicMethod() && inService() && @annotation(eventJournal) && args(entity,..)", returning = "id") 
// ... 

@AfterThrowing(pointcut = "isActive() && anyPublicMethod() && inService() && @annotation(eventJournal) && args(entity,..)", throwing="ex") 
// ... 
+0

請提供示例 – gstackoverflow

+0

我已將詳細信息添加到原始帖子。 – gstackoverflow

+0

如何將細節添加到您不是原始海報的問題? – kriegaex

0

您可以編寫返回如果當前執行的是使用JUnit框架展開的方法。

該方法可以使用Thread.currentThread()。getStackTrace()檢查堆棧跟蹤並搜索MockitoJUnitRunner的存在。

我使用SpringJUnit4ClassRunner測試了這個解決方案,但我認爲可以使用MockitoJUnitRunner。

此外,還可以有我的靜態布爾字段,如:

private static boolean TEST_ENVIRONMENT = false; 

在本項目中的一類(而不是在您的測試),並檢查控制方法,而不是使用堆棧跟蹤的價值。

當您運行測試時,可以使用@BeforeClass註釋來設置TEST_ENVIRONMENT = true。

此解決方案僅爲您提供了一種方法來了解代碼是否從測試運行。

相關問題