【问题标题】:Testing Facades in MVC | Assert Return Type在 MVC 中测试 Facades |断言返回类型
【发布时间】:2015-10-20 08:41:07
【问题描述】:

所以在 MVC 项目中,我有 Facades,它使用 Services 来获取信息。

所以我想通过测试确保调用正确的服务方法来获取信息,并且我想检查我的外观方法的返回类型是否符合我的预期。

当然,例如,当我期望一个用户列表时,我可以只模拟一个,然后使用 when().thenReturn() 返回列表并断言输出是相同的

问题是,我觉得嘲笑一切很烦人。下面是 Facade 中的方法的示例:

public List<UserData> getUsersByRegion(final RegionModel userRegion)
    {
        final List<UserModel> userModels = userService.getUsersByRegion(userRegion);
        final List<UserData> userFacadeData = new ArrayList<UserData>();

        for (final userModel model : userModels)
        {
            final UserData userData = new UserData(model.getEmail());
            userFacadeData.add(userData);
        }
        return userFacadeData;
    }

我是测试新手,到目前为止我所理解的是,您在不知道实现的情况下测试某些东西。因此,作为一名测试人员,我不知道这个人是如何做到的,我只知道他需要使用 Userservice 并且我想要一个带有 UserData 的列表。所以我不知道,他使用model.getEmail() 来调用构造函数UserData()。

还有我不需要测试的 UserService,因为我会为此编写一个额外的测试。

因此,如果我现在想真正测试该方法对所有数据的作用,我需要模拟 UserModels、UserData、RegionModels 来创建一个asssertEquals 并使用when().thenReturn()。

问题是,这是一个相当短的方法。由于 Facades 用于抽象获取和转换信息的复杂性,因此您在其中有很多工作要做。所以当我有更大的方法时,我会有很多东西可以模拟。

那么这真的有必要吗,有什么我没有考虑的吗,或者我该如何处理?如果我嘲笑,例如,对 UserService 使用 when().thenReturn() 不是明智的做法,而不是仅仅让 UserService 返回自身,因为它可能会发生,UserService 可能有错误?

P.S.:在 JUnit/Mockito 中测试方法的返回类型的方法是什么?

谢谢!

【问题讨论】:

    标签: java testing junit mockito facade


    【解决方案1】:

    我认为你嘲笑的东西比你真正需要的要多。对于示例方法,您只需要模拟 userService 实例。至于返回类型检查,我认为你不应该真正测试它,因为 Java 是一种类型安全的语言。如果有某种机会,您返回了与预期不同的类型,那么您肯定会得到一个异常 - 很可能甚至在编译期间也是如此。您的示例方法的测试应如下所示:

    @Test
    public void testGetUsersByRegion() {
        final UserModel userModel = new UserModel(); // initialise this with all the data you need
        final List<UserModel> userModels = Collections.singletonList(userModel);
        final UserService userService = mock(UserService.class);
    
        doReturn(userModels).when(userService).getUsersByRegion(any(RegionModel.class));
    
        final UserData userData = new UserData(userModel.getEmail());
        final List<UserData> expectedResult = Collections.singletonList(userData);
    
        // this assumes you have an instance of your facade and you have injected the mock user service to it
        final List<UserData> actualResult = usersFacade.getUsersByRegion(testRegion);
    
        verify(userService).getUsersByRegion(eq(testRegion));
        assertEquals(expectedResult, actualResult);
    }
    

    【讨论】:

    • 谢谢!这真的很有帮助。但是,当我有多个 getUserMethods 时,例如一个我不需要区域的 getUserMethods,或者我可能需要另一个字段时怎么办?将 UserModel 等的创建封装在一个额外的 build() 方法中的最佳方法是什么,这样我就不必为每个方法在每个测试中实例化所有变量?
    • 没有秘诀 - 您需要找到最适合您的情况和架构的方案。您可以在测试类中拥有工厂方法,可以拥有可以根据需要创建自定义实例的集中式工厂,可以公开对模型类具有有限访问权限的构造函数......这些是我见过和使用过的一些方法,各有利弊。
    • 好的。但是我刚刚注意到的是,当你调用 usersFacade.getUsersByRegion(testRegion) 时,你在哪里启动了 testRegion?或者既然你声明了 any(RegionModel.class) 我可以做 RegionModel testregion = new RegionModel();并将其留空?
    • 是的。示例中省略了 testRegion 的初始化。在这种特殊情况下,我认为只使用默认构造函数就可以了。
    猜你喜欢
    • 2023-01-08
    • 1970-01-01
    • 2019-09-02
    • 2020-08-06
    • 2016-04-25
    • 2019-03-20
    • 2011-10-26
    • 1970-01-01
    • 2017-09-22
    相关资源
    最近更新 更多