【问题标题】:How do I unit-test Maven multi-module Spring app?如何对 Maven 多模块 Spring 应用程序进行单元测试?
【发布时间】:2013-10-28 04:55:04
【问题描述】:

我在尝试使用 Spring 对 Maven 多模块项目进行单元测试时遇到问题。

我有 4 个模块:

application-core
application-data
application-service
application-web

这是我的测试,在 application-core 模块中:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/config/application-context.xml")
public class TicketTest {

    @Mock
    ITicketDAO ticketDAO;

    @Autowired
    @InjectMocks
    ITicketCore ticketCore;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testRegisterTicket_Ticket_NotUsed_isValid() {
        Long ticketNumber = 0L;
        when(ticketDAO.getTicket(anyLong())).thenReturn(null);
        final boolean isValidTicket = ticketCore.validateTicket(ticketNumber);
        assertTrue(isValidTicket);
    }

}

这是实现:

@Component
@Scope("prototype")
public class TicketCore implements ITicketCore{
    private ITicketDAO ticketDao;

    @Autowired
    public TicketCore(ITicketDAO ticketDao) {
        this.ticketDao = ticketDao;
    }

    @Override
    public boolean validateTicket(Long ticketNumber) {
        ITicket ticket = ticketDao.getTicket(ticketNumber);
        return ticket != null;
    }
}

界面:

public interface ITicketDAO {
    ITicket getTicket(Long ticketNumber);
}

application-data 模块上实现ITicketDAO

@Service
public class TicketDAO implements ITicketDAO {
    @Override
    public ITicket getTicket(Long ticketNumber) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }
}

我在测试此代码时遇到问题,因为上下文找不到 ITicketDAO 的实现。这似乎很明显,因为当测试运行时,JUnit 并不关心将“其他模块”放入类路径中。

出于显而易见的原因,Spring 抛出 BeanCreationException

我说的对吗?

所以我想在没有 Spring 的情况下测试我的项目。

我该怎么做才能让我的测试运行没有任何问题???

我在测试文件夹/包中创建了虚拟类,它可以工作,但是...

我最终会在我的 application-core 模块的测试文件夹中拥有所有外部实现。

有更好的方法吗?

提前致谢。

更新:

application-data
application-service
application-web

所有这些都依赖于application-core。 Spring成功注入TicketCore(application-core)。我想要的是给 Spring “一些东西”(一个虚拟类)注入 ITicketDAO 只是为了运行测试。

<beans>
    <context:component-scan base-package="ve.gov.imat.transimat" />
    <context:annotation-config />

    <aop:config proxy-target-class="true" />
</beans>

【问题讨论】:

    标签: java spring unit-testing maven


    【解决方案1】:

    假设每个 Maven 模块都是一个完全独立的项目。对每个模块的代码进行专门的测试,并在包含运行它们所需的所有依赖项的模块中添加集成测试。

    您尚未提供有关模块之间依赖关系的任何信息,但您遇到的问题似乎是您需要一些接口实现以用于测试目的,但您的生产 bean 是在另一个模块中定义的.这就是 EasyMock 和 Mockito 等模拟框架的用途;它们允许您编写简单的占位符实现,以便您可以专门测试TicketCore,即使在真正的实现可用时使用它们也是一个好主意,这样您就可以确保一次只测试一个组件。

    TicketTest 中,您为ITicketDAO 正确定义了Mockito 模拟,但您的TicketCore 仍在尝试从Spring 自动获取bean,即使您尚未注册它。手动将您的 bean 注册到测试上下文中,或者将模拟的定义放在 @Configuration 中的 src/test 中。

    【讨论】:

    • 你能给我一个这部分的例子吗?要么手动将你的 bean 注册到测试上下文中,要么将模拟的定义放在 src/test 的 @Configuration 中。这意味着我需要我的ITicketDAO 的“虚拟类”实现?我也更新了问题。
    【解决方案2】:

    如果我对您的理解很好,您的问题是您的上下文文件引用了一个您在测试类路径中没有可用的类。

    原则上,测试不应该需要任何协作者的实现,只需要一个 sut。

    一种解决方案是在您的 test/resources 文件夹下创建一个 application-test-context.xml 文件,以用于您的测试而不是生产环境。在此文件中,您可以创建协作者的模拟

    <!-- Mock service for splitting jobs -->
    <bean factory-bean="mockControl" factory-method="createMock"
        primary="true">
        <constructor-arg value="net.compart.docpilot.model.service.JobSplitService" />
    </bean>
    

    【讨论】:

      猜你喜欢
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      • 2022-07-08
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 1970-01-01
      相关资源
      最近更新 更多