当我有一个想法,使用Spring Data Redis的时候,我想到了JPA, 想到了Spring Data Mongo,一想Spring Data统一了Dao层的编程模型,我就觉得我可以轻松驾驭Spring Data Redis,果然想法是天真的。当我准备启动项目的时候,就报了一个错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean of type 'com.example.demo.repository.VocabularyEntityRepository' that could not be found.
这时时间已经过去了许久。我想这时候就开始看官网了,首先是找到Spring Data Redis 的文档看了一番,然而并没有看到什么问题,一想到Spring Data Redis肯定是开箱即用的,也就是我不需要额外的配置,除非我使用的不是默认的配置,显然我是完全按照默认的配置来的,所以我排除了配置的原因。
@RedisHash("people")
public class Person {
@Id String id;
@Indexed String firstname;
String lastname;
Address hometown;
}
public class Address {
@GeoIndexed Point location;
}
再看@GeoIndexed注解就很亲切。
Find using Geo Index:
repository.findByHometownLocationNear(new Point(15, 37), new Distance(200, KILOMETERS)); List findByAddressLocationWithin(Circle circle)
Unit testing has several best practices that frameworks should follow. Three rules that (in my experience) all unit testing frameworks should follow:
Each unit test should run independently of all other unit tests.
The framework should detect and report errors test by test.
It should be easy to define which unit tests will run.
1.4 Testing with JUnit
JUnit annotations to provide resource initialization and cleanup methods: @BeforeEach, @BeforeAll, @AfterEach, and @AfterAll (starting from version 5); and @Before, @BeforeClass, @After, and @AfterClass (up to version 4)
Summary
This chapter has covered the following: Why every developer should perform some type of test to see if code actually works. Developers who use automatic unit tests can repeat these tests on demand to ensure that new code works and does not break existing tests. Writing simple unit tests, which are not difficult to create without JUnit. As tests are added and become more complex, writing and maintaining tests becomes more difficult. Introduction to JUnit as a unit testing framework that makes it easier to create, run, and revise unit tests. Stepping through a simple JUnit test.
2. Exploring core JUnit
2.1 Core annotations
These are the most important concepts:
A test class may be a top-level class, a static member class, or an inner class annotated as @Nested that contains one or more test methods.
Test classes cannot be abstract and must have a single constructor.
The constructor must have no arguments, or arguments that can be dynamically resolved at runtime through
dependency injection.
A test class is allowed to be package-private as a minimum requirement for visibility. It is no longer required that test classes be public, as was the case up to JUnit 4.x.
A test method is an instance method that is annotated with @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, or @TestTemplate.
A life cycle method is a method that is annotated with @BeforeAll, @AfterAll,@BeforeEach, or @AfterEach.
2.1.1 The @DisplayName annotation
2.1.2 The @Disabled annotation
It signals that the annotated test class or test method is disabled and should not be executed.
2.2 Nested tests
The typical use case is when two classes are tightly coupled, and it’s logical to provide direct access from the inner class to all instance variables of the outer class.
2.3 Tagged tests
If you are familiar with JUnit 4, tagged tests are replacements for JUnit 4 categories.
2.4 Assertions
To perform test validation, you use the assert methods provided by the JUnit Assertions class.
After the heading parameter from the assertAll method, we provide the rest of the arguments as a collection of executables—a shorter, more convenient way to assert that supplied executables do not throw exceptions.
The assertAll method will always check all the assertions that are provided to it, even if some of them fail—if any of the executables fail, the remaining ones will still be run.
The advantage of using lambda expressions as arguments for assertion methods is that all of them are lazily created, resulting in improved performance.
2.5 Assumptions
Sometimes tests fail due to an external environment configuration or a date or time zone issue that we cannot control. We can prevent our tests from being executed under inappropriate conditions.
2.6 Dependency injection in JUnit 5
JUnit 5 allows test constructors and methods to have parameters, but they need to be resolved through dependency injection.
2.6.1 TestInfoParameterResolver
2.6.2 TestReporterParameterResolver
2.6.3 RepetitionInfoParameterResolver
If a parameter in a method annotated with @RepeatedTest, @BeforeEach, or @AfterEach is of type RepetitionInfo, RepetitionInfoParameterResolver supplies an instance of this type. Then RepetitionInfo gets information about the current repetition and the total number of repetitions for a test annotated with @RepeatedTest.
2.7 Repeated test
2.8 Parameterized tests
Parameterized tests allow a test to run multiple times with different arguments. The great benefit is that we can write a single test to be performed using arguments that check various input data.
@ValueSource lets us specify a single array of literal values.
@EnumSource enables us to use enum instances.
@CsvSource to express argument lists as comma-separated values (CSV)
@CsvFileSource allows us to use CSV files from the classpath.
2.9 Dynamic tests
JUnit 5 introduces a dynamic new programming model that can generate tests at runtime. We write a factory method, and at runtime, it creates a series of tests to be executed. Such a factory method must be annotated with @TestFactory.
A dynamic test has a different life cycle than a standard test annotated with @Test. The methods annotated with @BeforeEach and @AfterEach are executed for the @TestFactory method but not for each dynamic test; other than these methods, there are no life cycle callbacks for individual dynamic tests. The behavior of @BeforeAll and @AfterAll remains the same; they are executed before all tests and at the end of all tests.
2.10 Using Hamcrest matchers
As we write more unit tests and assertions, we inevitably find that some assertions are big and hard to read.The goal is to simplify the assertion made in the test method.
The Hamcrest library Hamcrest is not a testing framework itself, but it helps us declaratively specify simple matching rules. These matching rules can be used in many situations, but they are particularly helpful for unit testing.
Summary
The core JUnit 5 classes related to assertions and assumptions.
Using JUnit 5 methods and annotations: the methods from the assertions and assumptions classes, and annotations like @Test, @DisplayName, and @Disabled
The life cycle of a JUnit 5 test, and controlling it through the @BeforeEach, @AfterEach, @BeforeAll, and @AfterAll annotations
Applying JUnit 5 capabilities to create nested tests and tagged tests (annotation:@Tag)
Implementing dependency injection with the help of test constructors and methods with parameters
Applying dependency injection by using different parameter resolvers (TestInfoParameterResolver, TestReporterParameterResolver)
Implementing repeated tests (annotation: @RepeatedTest) as another application of dependency injection
Parameterized tests, a very flexible tool for testing that consumes different data sets and dynamic tests created at runtime (annotations: @ParameterizedTest, @TestFactory)