// without annotation, we'd get "theName", but we want "name": @JsonProperty("name") public String getTheName() { return _name; }
// note: it is enough to add annotation on just getter OR setter; // so we can omit it here publicvoidsetTheName(String n) { _name = n; } }
@JsonIgnoreProperties 和 @JsonIgnore
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// means that if we see "foo" or "bar" in JSON, they will be quietly skipped // regardless of whether POJO has such properties @JsonIgnoreProperties({ "foo", "bar" }) publicclassMyBean { // will not be written as JSON; nor assigned from JSON: @JsonIgnore public String internal;
// no annotation, public field is read/written normally public String external;
@JsonIgnore publicvoidsetCode(int c) { _code = c; }
// note: will also be ignored because setter has annotation! publicintgetCode() { return _code; } }
//不强制要求注册类(注册行为无法保证多个 JVM 内同一个类的注册编号相同;而且业务系统中大量的 Class 也难以一一注册) kryo.setRegistrationRequired(false); //默认值就是 false,添加此行的目的是为了提醒维护者,不要改变这个配置
//Fix the NPE bug when deserializing Collections. ((DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy()) .setFallbackInstantiatorStrategy(newStdInstantiatorStrategy());
@java.lang.Override publicbooleanequals(final java.lang.Object o) { if (o == this) returntrue; if (o == null) returnfalse; if (o.getClass() != this.getClass()) returnfalse; if (!super.equals(o)) returnfalse; finalPersonother= (Person)o; if (this.name == null ? other.name != null : !this.name.equals(other.name)) returnfalse; if (this.gender == null ? other.gender != null : !this.gender.equals(other.gender)) returnfalse; if (this.ssn == null ? other.ssn != null : !this.ssn.equals(other.ssn)) returnfalse; returntrue; }
@java.lang.Override publicinthashCode() { finalintPRIME=31; intresult=1; result = result * PRIME + super.hashCode(); result = result * PRIME + (this.name == null ? 0 : this.name.hashCode()); result = result * PRIME + (this.gender == null ? 0 : this.gender.hashCode()); result = result * PRIME + (this.ssn == null ? 0 : this.ssn.hashCode()); return result; } }
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `io.github.dunwu.javatech.bean.lombok.BuilderDemo01` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (String)"{"name":"demo01"}"; line: 1, column: 2] at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1432) at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1062) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3214) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3182) at io.github.dunwu.javatech.bean.lombok.BuilderDemo01.main(BuilderDemo01.java:22)
String to Complex Type if the Complex Type contains a String constructor
字符串和有字符串构造器的复杂类型(类)
String to Map
字符串和 Map
Collection to Collection
集合和集合
Collection to Array
集合和数组
Map to Complex Type
Map 和复杂类型
Map to Custom Map Type
Map 和定制 Map 类型
Enum to Enum
枚举和枚举
Each of these can be mapped to one another: java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Calendar, java.util.GregorianCalendar
<!-- You are responsible for mapping everything between ClassA and ClassB --> <converter type="org.dozer.converters.TestCustomHashMapConverter" > <class-a>org.dozer.vo.TestCustomConverterHashMapObject</class-a> <class-b>org.dozer.vo.TestCustomConverterHashMapPrimeObject</class-b> </converter> </custom-converters> </configuration> </mappings>
Denotes that a method is a test method. Unlike JUnit 4’s @Test annotation, this annotation does not declare any attributes, since test extensions in JUnit Jupiter operate based on their own dedicated annotations. Such methods are inherited unless they are overridden.
@ParameterizedTest
Denotes that a method is a parameterized test. Such methods are inherited unless they are overridden.
@RepeatedTest
Denotes that a method is a test template for a repeated test. Such methods are inherited unless they are overridden.
@TestFactory
Denotes that a method is a test factory for dynamic tests. Such methods are inherited unless they are overridden.
@TestInstance
Used to configure the test instance lifecycle for the annotated test class. Such annotations are inherited.
@TestTemplate
Denotes that a method is a template for test cases designed to be invoked multiple times depending on the number of invocation contexts returned by the registered providers. Such methods are inherited unless they are overridden.
@DisplayName
Declares a custom display name for the test class or test method. Such annotations are not inherited.
@BeforeEach
Denotes that the annotated method should be executed beforeeach@Test, @RepeatedTest, @ParameterizedTest, or @TestFactory method in the current class; analogous to JUnit 4’s @Before. Such methods are inherited unless they are overridden.
@AfterEach
Denotes that the annotated method should be executed aftereach@Test, @RepeatedTest, @ParameterizedTest, or @TestFactory method in the current class; analogous to JUnit 4’s @After. Such methods are inherited unless they are overridden.
@BeforeAll
Denotes that the annotated method should be executed beforeall@Test, @RepeatedTest, @ParameterizedTest, and @TestFactory methods in the current class; analogous to JUnit 4’s @BeforeClass. Such methods are inherited (unless they are hidden or overridden) and must be static (unless the “per-class” test instance lifecycle is used).
@AfterAll
Denotes that the annotated method should be executed afterall@Test, @RepeatedTest, @ParameterizedTest, and @TestFactory methods in the current class; analogous to JUnit 4’s @AfterClass. Such methods are inherited (unless they are hidden or overridden) and must be static (unless the “per-class” test instance lifecycle is used).
@Nested
Denotes that the annotated class is a nested, non-static test class. @BeforeAll and @AfterAllmethods cannot be used directly in a @Nested test class unless the “per-class” test instance lifecycle is used. Such annotations are not inherited.
@Tag
Used to declare tags for filtering tests, either at the class or method level; analogous to test groups in TestNG or Categories in JUnit 4. Such annotations are inherited at the class level but not at the method level.
@Disabled
Used to disable a test class or test method; analogous to JUnit 4’s @Ignore. Such annotations are not inherited.
@ExtendWith
Used to register custom extensions. Such annotations are inherited.
@BeforeAll publicstaticvoidbeforeAll() { person = newPerson("John", "Doe"); }
@Test voidstandardAssertions() { assertEquals(2, 2); assertEquals(4, 4, "The optional assertion message is now the last parameter."); assertTrue('a' < 'b', () -> "Assertion messages can be lazily evaluated -- " + "to avoid constructing complex messages unnecessarily."); }
@Test voidgroupedAssertions() { // In a grouped assertion all assertions are executed, and any // failures will be reported together. assertAll("person", () -> assertEquals("John", person.getFirstName()), () -> assertEquals("Doe", person.getLastName())); }
@Test voiddependentAssertions() { // Within a code block, if an assertion fails the // subsequent code in the same block will be skipped. assertAll("properties", () -> { StringfirstName= person.getFirstName(); assertNotNull(firstName);
// Executed only if the previous assertion is valid. assertAll("first name", () -> assertTrue(firstName.startsWith("J")), () -> assertTrue(firstName.endsWith("n"))); }, () -> { // Grouped assertion, so processed independently // of results of first name assertions. StringlastName= person.getLastName(); assertNotNull(lastName);
// Executed only if the previous assertion is valid. assertAll("last name", () -> assertTrue(lastName.startsWith("D")), () -> assertTrue(lastName.endsWith("e"))); }); }
@Test voidtimeoutNotExceeded() { // The following assertion succeeds. assertTimeout(ofMinutes(2), () -> { // Perform task that takes less than 2 minutes. }); }
@Test voidtimeoutNotExceededWithResult() { // The following assertion succeeds, and returns the supplied object. StringactualResult= assertTimeout(ofMinutes(2), () -> { return"a result"; }); assertEquals("a result", actualResult); }
@Test voidtimeoutNotExceededWithMethod() { // The following assertion invokes a method reference and returns an object. StringactualGreeting= assertTimeout(ofMinutes(2), AssertionsDemo::greeting); assertEquals("Hello, World!", actualGreeting); }
@Test voidtimeoutExceeded() { // The following assertion fails with an error message similar to: // execution exceeded timeout of 10 ms by 91 ms assertTimeout(ofMillis(10), () -> { // Simulate task that takes more than 10 ms. Thread.sleep(100); }); }
@Test voidtimeoutExceededWithPreemptiveTermination() { // The following assertion fails with an error message similar to: // execution timed out after 10 ms assertTimeoutPreemptively(ofMillis(10), () -> { // Simulate task that takes more than 10 ms. Thread.sleep(100); }); }
@Test voidtestOnlyOnCiServer() { assumeTrue("CI".equals(System.getenv("ENV"))); // remainder of test }
@Test voidtestOnlyOnDeveloperWorkstation() { assumeTrue("DEV".equals(System.getenv("ENV")), () -> "Aborting test: not on developer workstation"); // remainder of test }
@Test voidtestInAllEnvironments() { assumingThat("CI".equals(System.getenv("ENV")), () -> { // perform these assertions only on the CI server assertEquals(2, 2); });
// perform these assertions in all environments assertEquals("a string", "a string"); }
@Test @DisplayName("it is no longer empty") voidisNotEmpty() { assertFalse(stack.isEmpty()); }
@Test @DisplayName("returns the element when popped and is empty") voidreturnElementWhenPopped() { assertEquals(anElement, stack.pop()); assertTrue(stack.isEmpty()); }
@Test @DisplayName("returns the element when peeked but remains not empty") voidreturnElementWhenPeeked() { assertEquals(anElement, stack.peek()); assertFalse(stack.isEmpty()); } } } }
@RepeatedTest(value = 1, name = RepeatedTest.LONG_DISPLAY_NAME) @DisplayName("Details...") voidcustomDisplayNameWithLongPattern(TestInfo testInfo) { assertEquals(testInfo.getDisplayName(), "Details... :: repetition 1 of 1"); }
@RepeatedTest(value = 5, name = "Wiederholung {currentRepetition} von {totalRepetitions}") voidrepeatedTestInGerman() { // ... }
}
参数化测试
1 2 3 4 5
@ParameterizedTest @ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" }) voidpalindromes(String candidate) { assertTrue(isPalindrome(candidate)); }
// 其他用来验证函数是否被调用的方法 verify(mock, never()).someMethod("never called"); verify(mock, atLeastOnce()).someMethod("called at least once"); verify(mock, atLeast(2)).someMethod("called at least twice"); verify(mock, times(5)).someMethod("called five times"); verify(mock, atMost(3)).someMethod("called at most 3 times"); }