2014-01-14 32 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

相关问题