2016-02-22 73 views
0

我知道這個問題非常大,但我只想清除我所處的情況。 我正在使用消息代理使用JMS消息的應用程序。 我們在消費者方面使用駱駝路線。路徑生成器中所需的所有對象都是通過使用spring的構造函數注入來注入的。 我想嘲笑實際處理的行爲,一旦消費者從隊列中收到消息。所有類都通過彈簧配置加載。 下面是三類: CustomRouteBuilder.java如何用spock中的模擬對象替換構造函數注入對象

public CustomRouteBuilder extends RouteBuilder{ 

private CustomRouteAdapter customAdapter; 
    public CustomRouteBuilder (CustomRouteAdapter customAdapter){ 
    this.customAdapter = customAdapter 
    } 
    public void configure(RouteDefinition route){ 
    route.bean(customAdapter); 
    } 

} 

CustomRouteAdapter.java

public class CustomRouteAdapter { 
    private Orchestrator orchestrator; 
    public CustomRouteAdapter (Orchestrator orchestrator){ 
    this.orchestrator = orchestrator; 
    } 

    @Handler 
    public void process(String message){ 
    orchestrator.generate(message) ; 
    } 
} 

Orchestrator.java

public class Orchestrator{ 
    private Service service; 
    public Orchestrator(Service service){ 
    this.service = service; 
    } 

    public void generateData(String message){ 
    service.process(message); 
    } 
} 

按照我們的要求,我們需要加載該配置文件,然後使用spock編寫功能測試。 以下是我的

CustomRouteBuilderTest.groovy文件。

import org.springframework.test.util.ReflectionTestUtils 
import spock.lang.Specification 

@ContextConfiguration(classes=[CustomRouteBuilderTest.Config.class]) 
class CustomRouteBuilderTest extends Specification{ 
    private static final String message = "Hello"; 
Orchestrator orchestrator; 
@Autowired 
CustomRouteAdapter customRouteAdapter; 

def setup(){ 
    orchestrator = Mock(Orchestrator) 
    ReflectionTestUtils.setField(customRouteAdapter,"orchestrator",orchestrator) 
    orchestrator.generate(message) 
} 

private String getMessageAsJson() { 
    //return json string; 

} 


private String getMessage() { 
    // return message; 
} 

private Map<String, Object> doMakeHeaders() { 

    //Create message headers 
} 


private void doSendMessage(){ 
    Thread.sleep(5000) 
    Map<String,Object> messageHeader = doMakeHeaders() 
    byte [] message = getMessageAsJson().getBytes() 

    CamelContext context = new DefaultCamelContext() 
    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(jmsBrokerUrl) 
    context.addComponent("activeMQComponent",JmsComponent.jmsComponent(connectionFactory)) 
    ProducerTemplate template = context.createProducerTemplate() 
    context.start(); 
    template.sendBodyAndHeaders("queueName", message, messageHeader) 
} 

def "test message consumption"(){ 
    given: 
    doSendMessage() 
} 

    @Configuration 
    @Import([FunctionalTestCommonConfig.class,CustomRouteBuilderConfig.class]) 
    @PropertySource(value="classpath:test.properties") 
    static class Config{ 
    } 
} 

這裏是即使我使用ReflectionTestUtils注入嘲笑對象適配器的問題,我不能夠正確地定義其行爲。 當收到消息時,管絃樂器試圖處理它。 我的要求是: 適配器應該從駝峯路由中自動調用發生,但是當從適配器調用orechestrator.generate時會發生 ,那麼什麼都不應該發生,它應該簡單地返回。 但是這裏沒有那樣的事情正在發生。 每次我發送消費者(RouteBuilder)接收它,並調用處理程序函數然後調用

orchestrator.generate(message) 

功能和協調器開始處理並拋出從服務級別的異常的消息。 任何人都可以幫助我。

+0

你確定'CustomRouteAdapter'沒有被代理嗎?或者'orchestrator'字段不是最終的?執行測試時你有NPE嗎? –

+0

此前它是最終的。我刪除了最終修飾符,然後再次測試代碼。仍然是同樣的事情。根據這段代碼,我本應該收到NPE,但沒有收到。它調用service.process(消息)並從那裏獲得自定義的ServiceException。 –

+0

檢查調試器,但你沒有正確注入模擬,它應該拋出一個NPE與你發佈的代碼:-)另外,在groovy中,你不需要ReflectionTestUtils,如果該字段不是最終的,你可以寫'customRouteAdapter.orchestrator = ..' –

回答

0

我想你的bean已經被Spring代理,並且這個代理使用cglib(因爲你看到了CustomRouteBuilder$$EnhancerBySpringCGLIB$$ad2783ae)。

如果是真的的話,你沒有@Autowired在測試你的CustomRouteAdapter但cglib代理的真實實例:春天創建一個新的類,擴展realclass,並重寫這個類的所有方法。新方法委託給實際實例。

當您更改orchestrator字段時,您實際上正在更改代理的orchestrator字段,該字段未由實際實例使用。

有severals方式來實現你想要做什麼:

  1. CustomRouteAdapter
  2. 添加setOrchestrator方法在Spring配置創建模擬,讓春天注入該模仿,而不是一個真正的實例Orchestrator的
  3. 注入orchestrator在現實實例(醜陋! - 我不建議你的是,它沒有在你的代碼的可測試性幫助)

    customRouteAdapter.targetSource.target.orchestrator = _themock_ 
    
+0

我嘗試了在customRouteAdapter中添加setOrchestrator的第一個選項,它工作正常。謝謝,非常感謝,我也會嘗試其他選項。 –

相關問題