In JUnit, it is an element responsible for value verification Understand "assertions" and "Matcher API".
Assertion literally means affirmation or assertion.
JUnit can be roughly divided
Unit test is performed in the above three steps. What is an assertion in JUnit? This is the third mechanism for performing "comparison verification between assumed results and execution results".
In the actual code, use it as follows.
Assertion example.java
int expected = 1;
int actual = calc();
assertThat(actual, is(expected));
By writing like this, the test Assert that actual is expected. (Assert that actual is expected.) Can be written in natural language (spoken English).
The method ```is (expected) `` `that appeared in the source code mentioned earlier is It is a static method implemented in the CoreMatcher class of Matcher API. The Matcher API is for assertions that provide a ** value comparison method **. It is a mechanism to provide ** value verification method **, Previously it was implemented only in the JUnit extension library Hamcrest, It is now built into JUnit itself.
Verify that the values are equivalent.
assertThat(actual, is(expected));
Invert the verification result returned by Matcher. It can also be applied to Matchers other than is.
assertThat(actual, is(not(expected)));
Since the is method has a type parameter, you cannot pass a null value. Therefore, if you want to perform null verification, use the nullValue method.
assertThat(actual, is(nullValue()));
/*
The following writing style is also possible,
It is customary to write the above in order to write in a way that is closer to natural language.
*/
assertThat(actual, nullValue());
Verify that the value is not null.
assertThat(actual, is(notNullValue()));
//Synonymous with
assertThat(actual, is(not(nullValue()));
Verify that the values are equivalent.
Whereas the is method compares by equals
, sameInstance makes a comparison by `` = relatively
.
assertThat(actual, is(sameInstance(expected)));
Verify that the value inherits the expected value.
assertThat(actual, is(instanceOf(Serializable.class)));
For measured values that are iterative (have an iterator) like a collection class Verify that the expected value is included.
List<String> actual = getList();
assertThat(actual, hasItem(expected));
The content to be verified is the same as hasItem, except that it takes a variable length argument to the assumed value. A useful Matcher to verify that all expected values are included, regardless of order.
List<String> actual = getList();
assertThat(actual, hasItem(expected1, expected2));
Another extension library called hamcrest-library It provides a Matcher that can be used for general-purpose verification of collections, numbers, texts, etc. There are various other extension libraries, so before introducing the custom Matcher introduced below, It's a good idea to look for a Matcher that is already available.
Matcher can create a custom Matcher that does its own validation. Here, we will implement Matcher that meets the following requirements.
-When comparing and verifying the Date class, compare up to year, month, and day. -Output the assumed value and the measured value in the following format Format: is "Assumed value (yyyy / mm / dd)" but actual is "Actual value (yyyy / mm / dd)"
The following is the implementation of Matcher that meets the above requirements and its call processing.
DateTest.java
import static jp.sample.matcher.IsDate.*;
~abridgement~
assertThat(new Date(), is(dateOf(2020, 4, 12)));
IsDate.java
// 1.Declaration of Matcher class
public class IsDate extends BaseMatcher<Date> {
// 3.Implementation of a mechanism to hold assumed values
private final int yyyy;
private final int mm;
private final int dd;
Object actual;
// 3.Implementation of a mechanism to hold assumed values
IsDate(int yyyy, int mm, int dd) {
this.yyyy = yyyy;
this.mm = mm;
this.dd = dd;
}
// 4.Implementation of verification process
@Override
public boolean matches(Object actual) {
this.actual = actual;
if (!(actual instanceof Date)) {
return false;
}
Calendar cal = Calendar.getInstance();
cal.setTime((Date) actual);
if (yyyy != cal.get(Calendar.YEAR)) {
return false;
}
if (mm != cal.get(Calendar.MONTH)) {
return false;
}
if (dd != cal.get(Calendar.DATE)) {
return false;
}
return true;
}
// 5.Implementation of error messages
@Override
public void describeTo(Description desc) {
desc.appendValue(String.format("%d/%02d/%02d", yyyy, mm, dd));
if (actual != null) {
desc.appendText(" but actual is ");
desc.appendValue(
new SimpleDateFormat("yyyy/MM/dd").format((Date) actual));
}
}
// 2.Implementation of validation method
public static Matcher<Date> dateOf(int yyyy, int mm, int dd) {
return new IsDate(yyyy, mm, dd);
}
}
The org.hamcrest.Matcher interface as an implementation class for custom Matcher Implement, but direct implementation of the Matcher interface is deprecated. So we are implementing the Matcher interface Implement by inheriting org.hamcrest.BaseMatcher.
BaseMatcher has the measured value as a type parameter.
/*
public class [Arbitrary class name] extends BaseMatcher<[Measured value type]> {
}
*/
public class IsDate extends BaseMatcher<Date> {
}
Implement the method to be passed to the second argument of assertThat method. Since the assumed value is passed to the second argument, define the constructor of Matcher class Initialize the Matcher class with the expected values. For the mechanism for holding the assumed value, refer to "3. Implementation of the mechanism for holding the assumed value".
/*
public static Matcher<[Measured value type]> [Arbitrary method name]([Valuerequiredforinitialization]) {
return [Matcher class constructor];
}
*/
public static Matcher<Date> dateOf(int yyyy, int mm, int dd) {
return new IsDate(yyyy, mm, dd);
}
Actual measurement values and assumed values are required to verify the values. Therefore, the Matcher class implements a mechanism to hold them as members.
//Member holding the expected value
private final int yyyy;
private final int mm;
private final int dd;
//Member holding the measured value
Object actual;
//Constructor to set the expected value
IsDate(int yyyy, int mm, int dd) {
this.yyyy = yyyy;
this.mm = mm;
this.dd = dd;
}
When the assertThat method is executed, in the process The matches method defined in the Matcher interface is called. If the return value is false in the matches method, the test fails, and if it is true, the test is successful. Since the measured value is taken as an argument, it is verified with the assumed value held by the Matcher class. Implement so that true is returned if the verification result is as expected, and false if it is different.
@Override
public boolean matches(Object actual) {
//Hold the passed measured value as a member of the Matcher class
this.actual = actual;
//Type check(Write promised)
if (!(actual instanceof Date)) {
return false;
}
//The following is an original implementation, so implement it according to the purpose
Calendar cal = Calendar.getInstance();
cal.setTime((Date) actual);
if (yyyy != cal.get(Calendar.YEAR)) {
return false;
}
if (mm != cal.get(Calendar.MONTH)) {
return false;
}
if (dd != cal.get(Calendar.DATE)) {
return false;
}
return true;
}
Like the matches method, the method defined in the Matcher interface. It is called only when the test result is unsuccessful, and the error message is defined here.
@Override
public void describeTo(Description desc) {
//Expected value output
desc.appendValue(String.format("%d/%02d/%02d", yyyy, mm, dd));
//Output of measured value
if (actual != null) {
desc.appendText(" but actual is ");
desc.appendValue(
new SimpleDateFormat("yyyy/MM/dd").format((Date) actual));
}
}
Output result to console
java.lang.AssertionError:
Expected: is "2011/02/10" but actual is "2012/03/08"
got: <Thu Mar 08 23:02:49 JST 2012>
Error message template
[Error class name]
Expected: is [Message defined by describeTo method]
got: [Measured value toString output result]
//When a character string is passed as an argument
"2012/03/08" (Value enclosed in double quotes)
//When an object is passed as an argument
<Thu Mar 08 23:02:49 JST 2012> (ToString output result of the passed object)
but actual is (Not surrounded by double quotes)
This article was written with reference to the following information.
-[Introduction to JUnit Practice ── Systematic Unit Testing Techniques](https://www.amazon.co.jp/JUnit%E5%AE%9F%E8%B7%B5%E5%85%A5%E9 % 96% 80-% E4% BD% 93% E7% B3% BB% E7% 9A% 84% E3% 81% AB% E5% AD% A6% E3% 81% B6% E3% 83% A6% E3% 83% 8B% E3% 83% 83% E3% 83% 88% E3% 83% 86% E3% 82% B9% E3% 83% 88% E3% 81% AE% E6% 8A% 80% E6% B3% 95-WEB-PRESS-plus-ebook / dp / B07JL78S95)