In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
Most people do not understand the knowledge points of this "JUnit5 basic case Analysis" article, so the editor summarizes the following content, detailed content, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this "JUnit5 basic case Analysis" article.
Design philosophy
The new architectural design (which we'll talk about later) focuses on high scalability. What if there is any divine testing technology (at least for our vast Java? They may also be implemented under the architecture of JUnit 5.
For now, however, the basics involved are very similar to JUnit 4. The changes to JUnit 5 are not radical; on the contrary, the optimization process is meticulous and iterative in small steps. Therefore, developers should be very familiar with the new API. At least I am like this, and I'm sure you won't feel strange:
Class Lifecycle {@ BeforeAll static void initializeExternalResources () {System.out.println ("Initializing external resources...");} @ BeforeEach void initializeMockObjects () {System.out.println ("Initializing mock objects...");} @ Test void someTest () {System.out.println ("Running some test..."); assertTrue (true) } @ Test void otherTest () {assumeTrue (true); System.out.println ("Running another test..."); assertNotEquals (1,42, "Why wouldn't these be the same?");} @ Test @ Disabled void disabledTest () {System.exit (1) } @ AfterEach void tearDown () {System.out.println ("Tearing down...");} @ AfterAll static void freeExternalResources () {System.out.println ("Freeing external resources...");}}
Right? There hasn't been much change here.
JUnit 5 ready
Packet visibility
The most obvious change in JUnit 5 should be that it is no longer necessary to manually public test classes and test methods. The level of access visible to the package is sufficient. Of course, private (private) access is not possible. I think this change is reasonable and in line with our general intuition about visibility.
That's good! You can at least type a few fewer letters. But I'm sure you don't type these letters every time, do you? Still, it's good, with fewer keywords and less switching when you watch the test.
Life cycle of testing
@ Test
The most basic annotation in JUnit is @ Test. It marks the methods as test methods so that the build tool and IDE can identify and execute them.
Its API and function have not changed, but it no longer accepts any parameters. To test whether an exception is thrown, you can do it with the new assertion API; however, as far as I know, there is no alternative to the timeout option timeout.
Like JUnit 4, JUnit 5 creates a new instance for each test method.
Before and After
You may need to execute some code to complete some initialization or destruction before and after the test execution. In JUnit 5, there are four annotations you might use to do this:
@ BeforeAll
It is executed only once, before all tests and @ BeforeEach annotation methods.
@ BeforeEach
Execute before each test is executed.
@ AfterEach
Execute after each test is executed.
@ AfterAll
It is executed only once, after all tests and @ AfterEach annotated methods.
Because the framework creates a separate instance for each test, no test cases are born in the @ BeforeAll/@AfterAll method execution fashion. Therefore, these two methods must be defined as static methods.
The order of execution of different methods that annotate the same annotation is unpredictable, including for inherited methods. This is the decision of the development team after careful consideration to separate the focus of unit testing from integration testing. Integration testing may require closer collaboration between methods, but one unit test should not be dependent on other unit tests. Support for integration testing, also known as scenario testing, is also planned by the team.
Except for the different names, these annotations work exactly the same way as the annotations in JUnit 4. Coincidentally, in line with the mainstream opinion, I don't think this new name will convince me of its necessity. There is more discussion under this issue.
Disable testing
Today Friday, looking up, it's already 04:30. Do you want to go home when you don't want to work? I totally understand. Just click on the @ Disabled annotation on the test. If you have a conscience, it's great to write a reason to ignore the test, but you can do without this parameter.
@ Test @ Disabled ("you just can't run away on purpose, do you?") Void failingTest () {assertTrue (false);}
Test the lifecycle of a class
The prototype released by the JUnit team includes a description of the life cycle of the test class. Interestingly, this feature was not included in the release of the alpha version. This lifecycle model suggests using the same instance in multiple test methods of the class under test, so that we can interact among multiple test methods by changing the state of the object. (I repeat, it's more like a scenario test.)
As I said in the * * version of the public test, this feature is harmful in 99% of the scenarios, and only the other 1% is really useful. All I can say is, fortunately, this feature has been abandoned. Think about your unit tests. If they have to work by maintaining state between methods, the picture is too beautiful for me to see.
Assertion
If @ Test, @ Before..., @ After... If the annotation is the skeleton of a test suite, the assertion is its heart. After preparing the test case and executing the method of the class under test, the assertion ensures that you get the results you want. Otherwise, the current test failed.
Conventional assertion
General assertions are nothing more than checking the properties of an instance (for example, null and non-null, etc.), or comparing two instances (for example, checking whether two instance objects are equal). Either way, the assertion method can accept a string as an optional parameter, which provides the necessary description information if the assertion fails. If the process of providing error information is complex, it can also be wrapped in an lambda expression so that the message is actually constructed only when it really fails.
@ Test void assertWithBoolean () {assertTrue (true); assertTrue (this::truism); assertFalse (false, ()-> "Really" + "expensive" + "message" + ".");} boolean truism () {return true;} @ Test void assertWithComparison () {List expected = asList ("element"); List actual = new LinkedList (expected); assertEquals (expected, actual); assertEquals (expected, actual, "Should be equal.") AssertEquals (expected, actual, ()-> "Should" + "be" + "equal.") assertNotSame (expected, actual, "Obviously not the same instance.");}
As you can see, the API of JUnit 5 hasn't changed much. The naming of the assertion method is the same, and the method also accepts two parameters, an expected value and an actual value.
The order in which the expected and actual values are passed in is very important, whether for understanding the content of the test or understanding the error message in the event of a failure, but it is sometimes easy to get it wrong, which is very tricky. But when you think about it, there's no better way, unless you create a new assertion framework. Since there are corresponding products on the market, such as Hamcrest (ugh!) And AssertJ (yeah! The translator said: it is not clear where the cheering stem is) and so on, and it is obviously not worth wasting limited time to build wheels. After all, the most important thing is to make sure that your assertion library is focused on one thing, and you can save money by learning from existing implementations.
Oh, by the way, the failure message is now passed in as a parameter. I like this detail because it allows you to focus on what really matters-the two values that need to be asserted. Because of embracing Java 8, the truth assertion method now accepts the supplier parameter, which is another warm little detail.
Extended assertion
In addition to the general assertions that check for specific instances or properties, there are other types of assertions.
What I'm going to talk about here is not even a real assertion, what it does is force the test to fail and provide a failure message.
@ Test void failTheTest () {fail ("epicly");}
There is also the assertAll method, which takes a variable number of assertions as parameters, ensures that they are all executed, and then reports the error message, if any.
@ Test void assertAllProperties () {Address address = new Address ("New City", "Some Street", "No"); assertAll ("address", ()-> assertEquals ("Neustadt", address.city), ()-> assertEquals ("Irgendeinestra é e", address.street), ()-> assertEquals ("Nr", address.number)) } org.opentest4j.MultipleFailuresError: address (3 failures) expected: but was: expected: but was: expected: but was:
This property is useful when checking multiple property values of an object. As a general practice, the test will fail when * * assertions fail, and only * errors will be prompted, and you won't know whether the assertions of other values are successful, so you have to run the test again.
*, we finally have assertThrows and expectThrows methods. Both fail when the method under test does not throw an expected exception. The latter also returns the exception instance thrown for subsequent validation, such as asserting that the exception information contains correct information.
@ Test void assertExceptions () {assertThrows (Exception.class, this::throwing); Exception exception = expectThrows (Exception.class, this::throwing); assertEquals ("Because I can!", exception.getMessage ());}
Hypothesis / judgement (Assumptions)
Hypotheses / decisions allow you to run tests only when certain conditions are met. This feature reduces the run time and code repetition of the test component, especially if the hypotheses are not satisfied.
@ Test void exitIfFalseIsTrue () {assumeTrue (false); System.exit (1);} @ Test void exitIfTrueIsFalse () {assumeFalse (this::truism); System.exit (1);} private boolean truism () {return true;} @ Test void exitIfNullEqualsString () {assumingThat ("null" .equals (null), ()-> System.exit (1));}
The hypothesis / decision applies in two situations, either when you want to abort the test when certain conditions are not met, or if you want to perform (partially) the test only if certain conditions are met. The main difference is that aborted tests are reported in the form of disabled, where nothing is tested because the conditions are not met.
Test nesting
In JUnit 5, nested tests are almost effortless. You just need to add the @ Nested annotation to the nested class, and all the methods in the class will be executed by the engine:
Package org.codefx.demo.junit5; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class Nest {int count = Integer.MIN_VALUE; @ BeforeEach void setCountToZero () {count = 0 } @ Test void countIsZero () {assertEquals (0, count);} @ Nested class CountGreaterZero {@ BeforeEach void increaseCount () {count++;} @ Test void countIsGreaterZero () {assertTrue (count > 0) } @ Nested class CountMuchGreaterZero {@ BeforeEach void increaseCount () {count + = Integer.MAX_VALUE / 2;} @ Test void countIsLarge () {assertTrue (count > Integer.MAX_VALUE / 2) }
As you can see, the @ BeforeEach (and @ AfterEach) annotations in nested classes also work well. However, the construction order does not seem to have been written to the document, and their initialization order is from the outside to the inside. This also allows you to superimpose the preparation of test data for internal classes.
If a nested internal test wants to access the fields of an external test class, the nested class itself should not be static. But this also forbids the use of static methods, so the @ BeforeAll and @ AfterAll methods cannot be used in this scenario (or is there another way to implement them?)
You may be wondering what the use of nested internal test classes is. Personally, I use inner classes to test interfaces progressively, while others mostly use them to keep the test classes short and focused. The latter also has a classic example, provided by the JUnit team, which tests a stack:
Class TestingAStack {Stack stack; boolean isRun = false; @ Test void isInstantiatedWithNew () {new Stack ();} @ Nested class WhenNew {@ BeforeEach void init () {stack = new Stack () } / / some tests on 'stack', which is empty @ Nested class AfterPushing {String anElement = "an element"; @ BeforeEach void init () {stack.push (anElement);} / / some tests on' stack', which has one element... }}}
In the above example, the state change of the stack is reflected in the inner test class, where the inner class performs some tests based on its own scenario.
Test naming
JUnit 5 provides an annotation @ DisplayName that provides developers with more readable test class and test method information.
The above stack test example with this annotation looks like this:
@ DisplayName ("A stack") class TestingAStack {@ Test @ DisplayName ("is instantiated with new Stack ()") void isInstantiatedWithNew () {/ *... * /} @ Nested @ DisplayName ("when new") class WhenNew {@ Test @ DisplayName ("is empty") void isEmpty () {/ *. * /} @ Test @ DisplayName ("throws EmptyStackException when popped") void throwsExceptionWhenPopped () {/ *... * /} @ Test @ DisplayName ("throws EmptyStackException when peeked") void throwsExceptionWhenPeeked () {/ *.. * /} @ Nested @ DisplayName ("after pushing an element") class AfterPushing {@ Test @ DisplayName ("it is no longer empty") void isEmpty () {/ *... * /} @ Test @ DisplayName ("returns the element when popped and is empty") void returnElementWhenPopped () {/ *... * /} @ Test @ DisplayName ("returns the element when") Peeked but remains not empty ") void returnElementWhenPeeked () {/ *... * /}
This is a copy of the test results output that TDDer will be moved by and BDDer will shed tears.
The above is about the content of this article "JUnit5 basic introduction example Analysis". I believe we all have a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to know more related knowledge, please pay attention to the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.