崇明建设镇乡镇府网站,苏州计算机培训机构,wordpress系统,民政局网站建设工作总结对编写的代码进行单元测试几年前#xff0c;我是为我的数据访问代码编写单元测试的那些开发人员之一。 我正在孤立地测试所有内容#xff0c;我对自己感到非常满意。 老实说#xff0c;我认为自己做得很好。 哦#xff0c;男孩#xff0c;我错了#xff01; 这篇博客文章… 对编写的代码进行单元测试 几年前我是为我的数据访问代码编写单元测试的那些开发人员之一。 我正在孤立地测试所有内容我对自己感到非常满意。 老实说我认为自己做得很好。 哦男孩我错了 这篇博客文章描述了为什么我们不应该为数据访问代码编写单元测试并解释为什么我们应该用集成测试代替单元测试。 让我们开始吧。 单元测试错误问题的答案 我们为数据访问代码编写测试因为我们想知道它可以按预期工作。 换句话说我们想找到这些问题的答案 是否将正确的数据存储到使用的数据库 我们的数据库查询是否返回正确的数据 单元测试可以帮助我们找到想要的答案吗 嗯 单元测试的最基本规则之一是单元测试不应使用诸如数据库之类的外部系统 。 此规则不适用于当前情况因为存储正确信息和返回正确查询结果的责任由我们的数据访问代码和使用的数据库划分。 例如当我们的应用程序执行单个数据库查询时职责划分如下 负责创建执行的数据库查询的数据访问代码。 数据库负责执行数据库查询并将查询结果返回给数据访问代码。 问题是如果我们将数据访问代码与数据库隔离则可以测试数据访问代码是否创建了“正确的”查询但是我们无法确保所创建的查询返回正确的查询结果。 这就是为什么单元测试不能帮助我们找到想要的答案的原因 。 告诫故事Mo是问题的一部分 有段时间我为数据访问代码编写了单元测试。 当时我有两个规则 每段代码都必须单独进行测试。 让我们使用模拟。 我当时在一个使用Spring Data JPA的项目中工作而动态查询是使用JPA条件查询构建的。 如果您不熟悉Spring Data JPA则可能需要阅读Spring Data JPA教程的第四部分该教程解释了如何使用Spring Data JPA创建JPA条件查询 。 无论如何我创建了一个规范构建器类来构建Specification Person对象。 创建Specification Person对象之后将其转发给我的Spring Data JPA存储库该存储库执行查询并返回查询结果。 规范构建器类的源代码如下所示 import org.springframework.data.jpa.domain.Specification;import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;public class PersonSpecifications {public static SpecificationPerson lastNameIsLike(final String searchTerm) {return new SpecificationPerson() {Overridepublic Predicate toPredicate(RootPerson personRoot, CriteriaQuery? query, CriteriaBuilder cb) {String likePattern getLikePattern(searchTerm); return cb.like(cb.lower(personRoot.Stringget(Person_.lastName)), likePattern);}private String getLikePattern(final String searchTerm) {return searchTerm.toLowerCase() %;}};}
} 让我们看一下“验证”规范构建器类创建“正确”查询的测试代码。 请记住我是按照自己的规则编写该测试类的这意味着结果应该很棒。 PersonSpecificationsTest类的源代码如下所示 import org.junit.Before;
import org.junit.Test;
import org.springframework.data.jpa.domain.Specification;import javax.persistence.criteria.*;import static junit.framework.Assert.assertEquals;
import static org.mockito.Mockito.*;public class PersonSpecificationsTest {private static final String SEARCH_TERM Foo;private static final String SEARCH_TERM_LIKE_PATTERN foo%;private CriteriaBuilder criteriaBuilderMock;private CriteriaQuery criteriaQueryMock;private RootPerson personRootMock;Beforepublic void setUp() {criteriaBuilderMock mock(CriteriaBuilder.class);criteriaQueryMock mock(CriteriaQuery.class);personRootMock mock(Root.class);}Testpublic void lastNameIsLike() {Path lastNamePathMock mock(Path.class); when(personRootMock.get(Person_.lastName)).thenReturn(lastNamePathMock);Expression lastNameToLowerExpressionMock mock(Expression.class);when(criteriaBuilderMock.lower(lastNamePathMock)).thenReturn(lastNameToLowerExpressionMock);Predicate lastNameIsLikePredicateMock mock(Predicate.class);when(criteriaBuilderMock.like(lastNameToLowerExpressionMock, SEARCH_TERM_LIKE_PATTERN)).thenReturn(lastNameIsLikePredicateMock);SpecificationPerson actual PersonSpecifications.lastNameIsLike(SEARCH_TERM);Predicate actualPredicate actual.toPredicate(personRootMock, criteriaQueryMock, criteriaBuilderMock);verify(personRootMock, times(1)).get(Person_.lastName);verifyNoMoreInteractions(personRootMock);verify(criteriaBuilderMock, times(1)).lower(lastNamePathMock);verify(criteriaBuilderMock, times(1)).like(lastNameToLowerExpressionMock, SEARCH_TERM_LIKE_PATTERN);verifyNoMoreInteractions(criteriaBuilderMock);verifyZeroInteractions(criteriaQueryMock, lastNamePathMock, lastNameIsLikePredicateMock);assertEquals(lastNameIsLikePredicateMock, actualPredicate);}
} 这有道理吗 没有 我必须承认此测试对任何人都没有价值应该尽快删除。 此测试有三个主要问题 它不能帮助我们确保数据库查询返回正确的结果。 很难理解并使情况更糟它描述了查询的构建方式但没有描述查询应返回的内容。 这样的测试很难编写和维护。 事实是此单元测试是不应编写的测试的教科书示例。 它对我们没有任何价值但我们仍然必须维护它。 因此 这是浪费 但是如果我们为数据访问代码编写单元测试就会发生这种情况。 我们最终得到了一个测试套件无法测试正确的东西。 数据访问测试正确完成 我是单元测试的忠实拥护者但是在某些情况下它并不是工作的最佳工具。 这是其中一种情况。 数据访问代码与使用的数据存储有非常密切的关系。 这种关系是如此紧密以至于没有数据存储数据访问代码本身就没有用。 这就是为什么将我们的数据访问代码与二手数据存储区分开来是没有意义的。 解决这个问题很简单。 如果我们要为数据访问代码编写全面的测试则必须将数据访问代码与使用的数据存储一起进行测试。 这意味着我们必须忘记单元测试并开始编写集成测试 。 我们必须了解只有集成测试才能验证 我们的数据访问代码创建正确的数据库查询。 我们的数据库返回正确的查询结果。 如果您想知道如何为Spring支持的存储库编写集成测试则应该阅读我的博客文章标题为Spring Data JPA教程集成测试 。 它描述了如何为Spring Data JPA存储库编写集成测试。 但是在为使用关系数据库的任何存储库编写集成测试时可以使用相同的技术。 例如 为测试“ 将jOOQ与Spring结合使用”教程中的示例应用程序而编写的集成测试使用该博客文章中描述的技术。 摘要 这篇博客文章教会了我们两件事 我们了解到单元测试无法帮助我们验证数据访问代码是否正常运行因为我们无法确保将正确的数据插入到数据存储中或查询返回正确的结果。 我们了解到应该使用集成测试来测试数据访问代码因为数据访问代码和使用的数据存储之间的关系是如此紧密以至于没有必要将它们分开。 只剩下一个问题您是否还在为数据访问代码编写单元测试 翻译自: https://www.javacodegeeks.com/2014/07/writing-tests-for-data-access-code-unit-tests-are-waste.html对编写的代码进行单元测试