2014-01-14 33 views
3

我有我的單元測試中的任何問題,我沿着這個線的東西。如果使用Transactional註釋blargh函數,則模擬注入將在someService上覆蓋。如果我刪除交易,模擬停留在那裏。從看代碼看來,當服務中的函數用transactinal註釋時,Spring懶洋洋地加載服務,但是在服務沒有的時候急切地加載服務。這覆蓋了我注入的模擬。如何注入@ @Service的@Transactional

有沒有更好的方法來做到這一點?

@Component 
public class SomeTests 
{ 
    @Autowired 
    private SomeService someService; 

    @Test 
    @Transactional 
    public void test(){ 
    FooBar fooBarMock = mock(FooBar.class); 
    ReflectionTestUtils.setField(someService, "fooBar", fooBarMock); 
    } 
} 

@Service 
public class someService 
{ 
    @Autowired FooBar foobar; 

    @Transactional // <-- this causes the mocked item to be overridden 
    public void blargh() 
    { 
    fooBar.doStuff(); 
    } 
} 
+0

你可以生成代碼(和配置),將重現此? –

+0

從你的問題我假設你沒有單元測試,而是與Spring上下文和一些豆子的整合測試嘲笑。你如何將FooBar類的模擬注入到Spring上下文中?你使用Springockito還是嘗試手動執行?提供測試課程以增加獲得準確幫助的機會。 –

+0

你最終怎麼解決這個問題? –

回答

0

使用Spring @Profile功能 - 豆可以關聯到某一組,而組可以激活或通過註釋停用。

選中此blog postdocumentation更詳細的說明,這是如何定義的生產服務和兩組模擬服務的例子:

@Configuration 
@Profile("production") 
public static class ProductionConfig { 
    @Bean 
    public InvoiceService realInvoiceService() { 
     ... 
    } 
    ... 
} 

@Configuration 
@Profile("testServices") 
public static class TestConfiguration { 
    @Bean 
    public InvoiceService mockedInvoiceService() { 
     ... 
    } 
    ... 
} 

@Configuration 
@Profile("otherTestServices") 
public static class OtherTestConfiguration { 
    @Bean 
    public InvoiceService otherMockedInvoiceService() { 
     ... 
    } 
    ... 
} 

這是如何在測試中使用它們:

@ActiveProfiles("testServices") 
public class MyTest extends SpringContextTestCase { 
    @Autowired 
    private MyService mockedService; 

    // ... 
} 

@ActiveProfiles("otherTestServices") 
public class MyOtherTest extends SpringContextTestCase { 
    @Autowired 
    private MyService myOtherMockedService; 

    // ... 
} 
+0

請解釋這將做什麼。 –

+0

在這種情況下,我不是在嘲笑SomeService,而是SomeService使用的內部服務。 – Zipper

+0

我已經更新了另一種方式來確保只有測試bean被連接,使用顯式的XML配置進行測試並且不掃描服務包總是可以正常工作,雖然不太方便 –

2

或許你可以嘗試實施下列方式測試:

@Component 
@RunWith(MockitoJUnitRunner.class) 
public class SomeTests 
{ 
    @Mock private FooBar foobar; 
    @InjectMocks private final SomeService someService = new SomeService(); 


    @Test 
    @Transactional 
    public void test(){ 
    when(fooBar.doStuff()).then....; 
    someService.blargh() ..... 
    } 
} 

我現在無法嘗試,因爲沒有配置和相關代碼。但這是測試服務邏輯的常用方法之一。

+0

當然,它需要Mockito,但它可以讓您的測試變得簡單和乾淨。 – shippi

+0

這會工作,但對於測試,我有時需要模擬注入,有時我不需要。這取決於測試正在測試的內容。更糟糕的情況是我可以做到這一點,只需將這些需要的測試分開到自己的班級,但我希望將這些測試分組在一起。 – Zipper

+0

好吧,我現在和你在一起!也許我會單獨進行這些測試,並且會有一套迴歸測試和一套這樣的集成測試。不知道你的用例是注入真實對象而不是模擬。我試圖總是專注於測試我創建jUnit的bean,而其他所有東西都被嘲笑。 (並在另一層進行測試)。但正如我所說,我不知道你的用例。 – shippi

相關問題