繁体   English   中英

单元测试设计 & mocking

[英]Unit tests design & mocking

假设我有以下 class 并且我想对其进行测试。

class SearchRecommended:
    def __init__(self, request2template):
        self._r2t = request2template

    def handle(self, request: Request):
        return request.user().queries().add_recommendation_query().run(1).print(
            RecommendedSearchMedia(self._r2t(request))
        ).message(RecommendedSearchMessage)

.user()返回的 object 属于User “接口”,与数据库相关。

class User(Equalable, ABC):
    @abstractmethod
    def user_id(self):
        pass

    @abstractmethod
    def lang(self):
        pass

    @abstractmethod
    def queries(self) -> "UserQueries":
        pass

    @abstractmethod
    def subscriptions(self) -> "UserSubscriptions":
        pass

    @abstractmethod
    def notifications(self) -> "UserSubsNotifications":
        pass

    @abstractmethod
    def access(self) -> "UserAccess":
        pass

    def repr(self):
        return self.user_id()

UserQueriesUserSubscriptionsUserSubsNotificationsUserAccess也是数据库交互类的基类。

据我所知,单元测试应该是快速的,不应该使用实际的数据库连接。 单元测试也不应该对他们正在测试的代码的内部结构了解太多。

Mocking 整个数据库交互层很繁琐,但是 mocking 仅在被测方法中使用的方法似乎对内部代码“了解太多”。

我在.handle方法中的代码不应该可以自由地从User界面(或它被模拟的 object)和后续的持久层类(只要这些调用对于给定的接口是正确的)调用它喜欢的任何方法,除非我明确测试调用的方法的顺序?

我有什么问题吗?我该怎么办?

您的方法handle不适合在单元测试中进行测试。 handle唯一能做的就是与其他代码交互。 但是,为了测试与其他代码的交互,您宁愿使用集成测试。

背景是,对于任何类型的测试,您的目标都是发现错误。 通过单元测试,您可以尝试在隔离代码中找到错误。 但是,如果你真的隔离了你的代码 - 有什么错误可以找到?

您的代码中的错误更多地是“我是否以正确的顺序使用正确的 arguments 调用其他对象的正确方法,并且返回值将采用我期望的形式。” 所有这些问题都不会通过单元测试来回答,而是通过集成测试来回答。

您的单位需要确保 class 完成它应该做的事情。 为了实现您的 class 需要 function 的某些东西,在这种情况下是 class 用户的版本。

您的 class 足够了解 User 来调用其方法和方法的结果,因此您的测试有足够的能力让这些调用按预期工作。

您的模拟实际上不必制作假数据库或具有真正的功能,它只需要看起来像它。 如果您只关心确保按顺序调用数据层,只需让 function 链的每个步骤都将 var 设置为 true 或其他什么,并在测试结束时验证所有 var 是否为 true。 不是很好,但它确保这个 class 按预期调用数据层。

从长远来看,如果您一直不得不做这样的事情,请为 User 或类似的类做一个测试替身,根据需要添加功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM