Checked Exception Is Invalid For This Method
Definition of Checked Exceptions
In Java, exceptions are divided into two categories: checked exceptions and unchecked exceptions. Checked exceptions are those that must be declared in the method signature or handled within the method using try-catch blocks. These exceptions are checked by the compiler at compile-time to ensure that they are either caught or declared to be thrown by the method.
Explanation of Checked Exceptions in Java
Checked exceptions were introduced in Java to enforce proper exception handling and improve code robustness. They are typically used for exceptional conditions that can be reasonably expected to occur during the execution of a method. Examples of checked exceptions in Java include IOException, SQLException, and ClassNotFoundException.
By forcing the developer to either catch or declare these exceptions, checked exceptions help to prevent the propagation of unhandled exceptions, providing a more reliable code structure. This means that any potential exceptions are explicitly accounted for and cannot be ignored by the developer.
Drawbacks of Using Checked Exceptions
While checked exceptions have their benefits, they are not without their drawbacks. One of the main drawbacks is that they can clutter the codebase with unnecessary try-catch blocks. This can lead to code duplication and reduced readability.
Checked exceptions can also hinder method reusability and flexibility. If a method declares a checked exception, any code calling that method must also handle or declare the exception. This can quickly become burdensome, especially in cases where the calling code does not actually care about handling the exception.
Rationale for Invalidating Checked Exception in a Method
There are situations where invalidating the checked exception for a method can be beneficial. One such situation is when the method is part of a larger framework or library and the checked exception is not relevant to the clients, or it is too cumbersome for them to handle.
By invalidating the checked exception, the developers can provide a cleaner and more intuitive interface for the method, making it easier for clients to use. It removes the burden of having to handle or declare the checked exception when it is not necessary for the particular use case.
Alternate Approaches to Handling Exceptions in Method Implementation
When a checked exception is invalidated for a method, there can be alternate approaches to handle the exceptions internally. One approach is to convert the checked exception into an unchecked exception and throw it instead. This allows the method to propagate the exception without enforcing the client code to handle it.
Another approach is to log the exception and return a default or alternative value. This can be useful when the method’s purpose is to retrieve a value or perform an operation, and the exception does not significantly impact the result. It provides a graceful way to handle the exceptional condition without disrupting the flow of the program.
Advantages and Disadvantages of Invalidating Checked Exception
Invalidating a checked exception for a method has its advantages and disadvantages. The main advantage is improved code readability and simplicity. By removing unnecessary try-catch blocks, the code becomes cleaner and more maintainable.
Another advantage is increased flexibility and ease of use for the clients. Without the burden of having to handle or declare the checked exception, the clients can focus on the primary functionality of the method, resulting in more concise and intuitive code.
However, there are also disadvantages to invalidating checked exceptions. One disadvantage is the potential loss of information about exceptional conditions. By converting or suppressing the checked exception, important information about potential errors may be lost, making it harder to debug and maintain the code.
Invalidating checked exceptions can also result in the propagation of unchecked exceptions that are not explicitly accounted for in the code. This can lead to unexpected program behavior or even crashes if the unchecked exception is not properly handled.
FAQs
Q: What does it mean when a checked exception is invalidated for a method?
A: When a checked exception is invalidated for a method, it means that the method no longer enforces the handling or declaration of the checked exception. Clients calling the method are not required to handle or declare the exception, making the method interface cleaner and more intuitive.
Q: Can Mockito be used to throw exceptions in a method?
A: Yes, Mockito is a popular Java testing framework that supports throwing exceptions in a method for testing purposes. It allows developers to mock methods that throw exceptions, enabling them to simulate exceptional conditions and test the corresponding error handling.
Q: How can I mock a method that throws an exception?
A: In Mockito, you can mock a method that throws an exception using the `doThrow()` method. This allows you to specify the exception that should be thrown when the method is called. By mocking the method, you can control the behavior and test the exception handling in your code.
Q: Is it possible to use JUnit to test checked exceptions?
A: Yes, JUnit provides support for testing checked exceptions. You can use the `ExpectedException` rule or the `@Test` annotation’s `expected` attribute to specify the expected exception and validate that it is thrown during the test execution.
Q: How can I assert that a method throws an exception in Java?
A: In Java, you can use the `assertThrows()` method provided by JUnit to assert that a method throws an exception. This method takes the expected exception type and a `Executable` (typically a lambda expression) that represents the code that should throw the exception. If the specified exception is thrown, the assertion passes; otherwise, it fails.
Q: Can Mockito be used to mock a static method that throws a checked exception?
A: Yes, Mockito can be used to mock a static method that throws a checked exception. By using libraries such as PowerMock or Mockito with PowerMock, you can mock and control the behavior of static methods, including those that throw checked exceptions. However, care should be taken when mocking static methods, as it can introduce complexities and potential testing issues.
Checked Vs. Unchecked Exceptions In Java Tutorial – What’S The Difference?
How To Write Mockito For Checked Exception?
Mockito is a powerful tool that helps in writing effective unit tests by providing a way to create mock objects and stub their behaviors. However, Mockito by default cannot handle methods that throw checked exceptions. In this article, we will discuss the process of writing Mockito for checked exceptions and explore various scenarios where it can be applied.
Understanding Checked Exceptions and Mockito
Before diving into the process of writing Mockito for checked exceptions, it is essential to understand what exactly checked exceptions are. In Java, checked exceptions are a type of exception that the compiler forces the caller to handle or declare. This means that if a method throws a checked exception, the caller of that method must either handle the exception using a try-catch block or declare it in its own method signature using the “throws” clause.
Mockito, being a testing framework, aims to create mock objects that simulate the behavior of real objects. By default, Mockito cannot handle methods that throw checked exceptions because it is not aware of the exception type. However, there are several approaches that can be used to tackle this issue.
Using Mockito’s “doThrow” Method
The simplest way to write Mockito for a method that throws a checked exception is by using Mockito’s “doThrow” method. This method allows us to specify the exception type that should be thrown when a specific mocked method is invoked. Here’s an example:
“`java
@Test
public void testMethodWithCheckedException() throws SomeCheckedException {
SomeClass mock = Mockito.mock(SomeClass.class);
Mockito.doThrow(SomeCheckedException.class)
.when(mock)
.someMethod();
// Now, calling mock.someMethod() will throw SomeCheckedException
}
“`
In this example, we create a mock object of type SomeClass using Mockito.mock(). We then use Mockito.doThrow() to specify the exception we want to throw when the someMethod() is called on the mock object. This way, we can simulate the behavior of the real object, as if it was throwing a checked exception.
Creating a Custom Answer
Another approach to handling checked exceptions in Mockito is by creating a custom answer. Mockito’s Answer interface allows us to provide custom behavior for mocked methods. By implementing the Answer interface, we can define the behavior of the mock object to handle the checked exception. Here’s an example:
“`java
@Test
public void testMethodWithCheckedException() throws SomeCheckedException {
SomeClass mock = Mockito.mock(SomeClass.class);
Mockito.when(mock.someMethod()).thenAnswer(new Answer
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
throw new SomeCheckedException();
}
});
// Now, calling mock.someMethod() will throw SomeCheckedException
}
“`
In this example, we use Mockito.when() to specify that when the someMethod() is called on the mock object, it should answer using our custom answer. The custom answer, implemented using the Answer interface, throws the desired checked exception. This approach gives us more flexibility in handling different scenarios and exceptions.
Frequently Asked Questions (FAQs)
Q: Why does Mockito not handle checked exceptions by default?
A: Mockito is primarily designed to create mock objects and stub their behaviors. Handling checked exceptions is not part of its core functionality, as it is based on the philosophy of focusing on the behavior rather than the implementation details. However, Mockito provides various approaches to handle checked exceptions, as discussed in this article.
Q: Can Mockito handle multiple checked exceptions?
A: Yes, Mockito can handle multiple checked exceptions by using the approaches mentioned earlier. You can either use Mockito’s “doThrow” method to specify multiple exception types or create a custom answer that throws different types of checked exceptions based on the scenario.
Q: What happens if a method throws a checked exception that is not specified in the Mockito configuration?
A: If a method throws a checked exception that is not specified in the Mockito configuration, the test case will fail with an unhandled exception. To avoid this, ensure that all possible checked exceptions are handled or specified in the Mockito configuration.
Q: Can Mockito handle methods that throw runtime exceptions?
A: Yes, Mockito can handle methods that throw runtime exceptions by default. As runtime exceptions do not require explicit exception handling, Mockito can handle them without any additional configuration.
In conclusion, Mockito provides ways to handle checked exceptions by using the “doThrow” method or creating a custom answer. These approaches allow us to mimic the behavior of real objects that throw checked exceptions, enhancing the effectiveness of our unit tests. By understanding and implementing these techniques, developers can ensure that their Mockito-powered tests cover all possible scenarios, including those involving checked exceptions.
How To Use Checked Exception In Java?
Java’s exception handling mechanism allows developers to deal with various errors and exceptional conditions that may occur during the execution of a program. Exceptions in Java are categorized into two types: checked and unchecked. In this article, we will focus on checked exceptions and explore how to use them effectively in a Java program.
Understanding Checked Exceptions:
Checked exceptions are exceptions that must be declared by the caller of a method or caught by the enclosing method. These exceptions are enforced by the Java compiler during compilation, ensuring that developers handle them appropriately. The compiler will generate an error if a checked exception is not handled properly.
Checked exceptions represent exceptional conditions that can potentially occur during the execution of a program. They typically indicate error conditions that are beyond the control of the program itself, such as file I/O errors, network connection failures, database access problems, etc. By using checked exceptions, developers are forced to address and handle these potential problems explicitly, increasing the robustness and reliability of the code.
Declaring and Catching Checked Exceptions:
When working with checked exceptions, you need to be aware of two ways to handle them: declaring and catching.
1. Declaring Checked Exceptions:
When a method can potentially throw a checked exception, it needs to be declared using the `throws` keyword. For example, consider the following method that reads a file and throws a `FileNotFoundException`:
“`java
public void readFile() throws FileNotFoundException {
// code to read file
}
“`
By declaring the `FileNotFoundException` in the method signature, you are indicating to the caller of this method that it might throw this particular exception. This allows the caller to handle the exception appropriately or declare it further up the call stack.
2. Catching Checked Exceptions:
The second way to handle checked exceptions is by catching them within a try-catch block. This approach is used when you want to provide specific instructions on what actions should be taken when a particular exception occurs. The general syntax for catching checked exceptions is as follows:
“`java
try {
// code that might throw a checked exception
} catch (CheckedExceptionType exception) {
// code to handle or recover from the exception
}
“`
Here’s an example that demonstrates catching a `FileNotFoundException`:
“`java
try {
readFile();
} catch (FileNotFoundException exception) {
System.out.println(“File not found. Please provide a valid file.”);
}
“`
In this example, if the `readFile()` method throws a `FileNotFoundException`, the catch block will execute and display an error message to the user.
Best Practices for Handling Checked Exceptions:
When working with checked exceptions in Java, it is important to follow some best practices to ensure clean and maintainable code. Here are a few guidelines to consider:
1. Only catch exceptions that you can handle effectively: Avoid catching exceptions unless you know how to handle them properly. Catching exceptions without taking appropriate actions can mask underlying issues and lead to unexpected behavior.
2. Provide meaningful error messages: When catching a checked exception, it is essential to provide clear and meaningful error messages to help users understand the problem and take appropriate actions.
3. Use finally blocks for cleanup: If you need to perform cleanup activities, such as closing open resources, consider using a `finally` block. The `finally` block is executed regardless of whether an exception occurred or not, making it a suitable place to release resources.
4. Use checked exceptions judiciously: Checked exceptions introduce an extra burden on the caller, requiring them to handle or declare the exception. Therefore, it is recommended to use checked exceptions only when necessary, such as for I/O operations or external dependencies.
FAQs:
Q: What is the difference between checked and unchecked exceptions in Java?
A: Checked exceptions must be declared or caught, while unchecked exceptions do not require any explicit handling.
Q: Can we throw checked exceptions without declaring them?
A: No, checked exceptions must be declared using the `throws` clause in the method signature.
Q: Do all methods need to declare checked exceptions they can throw?
A: No, methods can either declare checked exceptions using the `throws` keyword or catch the exceptions within a try-catch block.
Q: Can we convert checked exceptions into unchecked exceptions?
A: Yes, we can wrap checked exceptions inside an unchecked exception or use a custom exception type to achieve this.
Q: Is it possible to catch multiple exceptions in a single catch block?
A: Yes, starting from Java 7, you can catch multiple exceptions with a single catch block by separating them with a pipe (|) symbol.
In conclusion, checked exceptions in Java provide a mechanism to handle and recover from potential exceptional conditions during program execution. By properly declaring and catching these exceptions, developers can ensure code reliability and enhance error handling. Remember to adhere to best practices and address checked exceptions appropriately, resulting in robust and maintainable code.
Keywords searched by users: checked exception is invalid for this method Checked exception is invalid for this method, Mockito throw exception, Mockito throw sql exception, mock method that throws exception, Checked exceptions, junit for checked exception, Assert throw exception Java, Mock static method
Categories: Top 19 Checked Exception Is Invalid For This Method
See more here: nhanvietluanvan.com
Checked Exception Is Invalid For This Method
In the world of programming, exception handling plays a crucial role in ensuring the reliability and robustness of software applications. Exceptions are unexpected events that occur during the execution of a program and are used to handle errors or exceptional conditions. Java, one of the most widely used programming languages, introduces the concept of checked exceptions to enforce proper exception handling. However, there are cases where using checked exceptions is not appropriate, and this article will delve into the reasons why checked exceptions are invalid for certain methods.
To understand why checked exceptions might be unsuitable for specific methods, we should first clarify the difference between checked and unchecked exceptions. Checked exceptions, also known as compile-time exceptions, are the exceptions that a method must declare in its signature using the “throws” keyword. When a method throws a checked exception, the caller of that method is obligated to handle or propagate the exception. In contrast, unchecked exceptions, also referred to as runtime exceptions, do not need to be declared in the method signature.
1. Reducing Boilerplate Code:
One of the primary reasons why checked exceptions may be undesirable for a method is the burden of handling or propagating them, which often leads to excessive boilerplate code. With checked exceptions, developers are constantly required to write try-catch blocks or include “throws” declarations, even for exceptions that cannot occur in practice. This adds unnecessary complexity and verbosity to the codebase, making it harder to read and understand.
2. Inevitable Runtime Exceptions:
Some methods are inherently associated with exceptional conditions that cannot be reasonably avoided. For instance, reading data from a file involves the risk of encountering a file not found exception. In such cases, it is more appropriate to use unchecked exceptions since these exceptional conditions are impossible to handle and recover from at runtime. By using unchecked exceptions, we eliminate the overhead of unnecessary try-catch blocks and focus on meaningful error handling.
3. Forced Exception Handling Leads to Messy Code:
Checked exceptions force the calling code to handle or propagate the exception. While this may seem beneficial in theory, it can lead to messy and convoluted code. In many situations, the caller of a method may not have the necessary information or context to handle the exception appropriately. In such cases, the propagation of the exception might be the only reasonable choice, but this imposes the exception handling burden on the caller’s caller. As a result, the code becomes harder to reason about and maintain.
4. Impedes Code Reusability and Flexibility:
Checked exceptions pose significant challenges when it comes to code reusability. When a checked exception is declared in a method’s signature, it becomes part of the method’s contract. If the method is intended to be reused in different contexts, the caller might not be aware or prepared to handle the potential exceptions that the method declares. This limits the flexibility of the code and requires the developer to anticipate all possible exceptions from reused methods, making the code more fragile and interdependent.
5. Handling Failure in a Unified Way:
Unchecked exceptions allow for a unified approach to handling exceptional conditions throughout the application. They provide the flexibility to create global exception handlers or interceptors that can gracefully handle any unexpected exception in a consistent manner. This approach simplifies the overall exception handling strategy and allows for a cleaner separation of concerns.
FAQs:
Q: Can we completely eliminate the usage of checked exceptions?
A: No, there are scenarios where checked exceptions might still be appropriate. For example, when dealing with external resources that require explicit cleanup (e.g., database connections, file handles), using checked exceptions can help ensure that the resources are properly freed.
Q: What about the principle of “fail fast”?
A: The principle of “fail fast” suggests that any potential exception should be explicitly accounted for, encouraging developers to handle exceptions as soon as they occur. While this principle has its merits, it does not necessarily imply the mandatory usage of checked exceptions. Unchecked exceptions can still provide a fail-fast approach by terminating the program if an exceptional condition arises.
Q: Are there any alternatives to checked exceptions?
A: Yes, in many cases, alternatives such as returning error codes or using custom exception hierarchies can be considered. These alternatives provide more flexibility in error handling and do not impose the rigid requirements of checked exceptions.
Q: What should we do with existing methods that already use checked exceptions?
A: Changing existing methods from checked to unchecked exceptions can have significant implications and should be undertaken with caution. It is essential to analyze the impact on the calling code, ensure appropriate error handling, and migrate gradually, considering the broader context of the application.
In conclusion, while checked exceptions can be useful in specific situations, there are instances where they are inappropriate and hinder code readability, reusability, and maintainability. By understanding the limitations and drawbacks of checked exceptions, developers can make informed decisions about when to use unchecked exceptions, resulting in cleaner and more maintainable codebases.
Mockito Throw Exception
Mockito provides a simple and intuitive way to throw exceptions when specific methods are invoked on mock objects. This is particularly useful when we want to simulate certain error conditions or exceptional behavior during our tests. By throwing exceptions, we can ensure that our code is handling these scenarios correctly and gracefully.
To throw an exception with Mockito, we need to use the `thenThrow` method from the `given` static class. This method allows us to specify the exception type that should be thrown when a specific method is called. Let’s take a look at an example:
“`
// Create a mock object
List
// Define the behavior of the mock object
Mockito.when(mockList.size()).thenThrow(new RuntimeException(“Error: Method not supported!”));
// Test the behavior of our code
try {
int size = mockList.size();
} catch (RuntimeException e) {
System.out.println(e.getMessage()); // Output: Error: Method not supported!
}
“`
In this example, we create a mock object of the `List` class using the `mock` method provided by Mockito. Then, we define the behavior of the mock object using the `when` method. We specify that when the `size` method is called on the mock object, it should throw a `RuntimeException` with the specified error message. Finally, we test the behavior by calling the `size` method and catching the exception that is thrown.
This feature of throwing exceptions can be especially useful when writing tests for error handling in our code. We can simulate different exceptions and observe how our code handles them. For example, suppose we have a method that reads data from a file and throws an `IOException` if the file is not found. We can mock the file reading operation, throw an `IOException`, and test whether our code gracefully handles the exception by providing an appropriate error message or taking any necessary recovery actions.
Now, let’s dive into some frequently asked questions about Mockito’s throw exception feature:
**Q: Can we throw checked exceptions using Mockito?**
A: Yes, Mockito supports throwing checked exceptions as well. You can use the `thenThrow` method to throw any checked exception by specifying its class.
**Q: Can we throw different exceptions for multiple invocations of the same method?**
A: Yes, Mockito allows us to throw different exceptions for different invocations of the same method. We can chain multiple `thenThrow` calls to define different behaviors for different scenarios.
**Q: How can we throw exceptions based on arguments passed to the method?**
A: Mockito provides the `argThat` method to match specific arguments passed to the method. We can use this method to conditionally throw exceptions based on the arguments. For example:
“`
Mockito.when(mockObject.someMethod(Mockito.argThat(argument -> argument > 10))).thenThrow(new IllegalArgumentException());
“`
**Q: Can we throw exceptions only for void methods?**
A: No, Mockito allows us to throw exceptions for any type of method, whether it returns a value or not. The `thenThrow` method can be used for both void and non-void methods.
**Q: Is there any way to control the order in which exceptions are thrown for different invocations?**
A: Yes, Mockito provides the `doThrow` method, which allows us to throw exceptions in a specific order. By using this method along with the `thenReturn` method, we can precisely control the behavior of our mock object.
In conclusion, Mockito’s throw exception feature enables us to simulate exceptional behavior and error conditions during unit testing. By throwing exceptions, we can ensure that our code handles those scenarios correctly. With the given examples and the FAQs section, you now have a solid understanding of how to use Mockito’s throw exception feature effectively in your testing process. So, go ahead and leverage this powerful feature to enhance the correctness and robustness of your Java code.
Mockito Throw Sql Exception
To begin with, let’s have a brief understanding of what SQL exceptions are. In Java, SQL exceptions are errors or conditions that occur while interacting with a database. These exceptions can occur due to various reasons, such as incorrect SQL syntax, connection failures, or violations of database constraints.
Throwing SQL exceptions during testing allows us to simulate real-life scenarios. For example, we may want to check the behavior of our code when a database connection fails or when an SQL statement encounters an error. Mockito helps us achieve this by allowing us to throw specific exceptions when certain methods are called.
To throw a SQL exception using Mockito, we first need to mock the objects and methods involved in the database interaction. We can accomplish this by using the Mockito framework and its mocking capabilities. Let’s take a look at a simple example:
“`java
@Test
public void testDatabaseInteraction() throws SQLException {
Connection connection = mock(Connection.class);
PreparedStatement statement = mock(PreparedStatement.class);
when(connection.prepareStatement(anyString())).thenReturn(statement);
when(statement.executeUpdate()).thenThrow(new SQLException(“Connection failed”));
// Code under test
DatabaseService service = new DatabaseService();
service.setConnection(connection);
service.updateData();
// Assertions
// …
}
“`
In this example, we create a mock object of the `Connection` class and the `PreparedStatement` class. We then define the behavior of these objects using the `when` and `thenReturn` methods provided by Mockito. In the `when` block, we specify the methods that we want to mock, and in the `thenReturn` block, we provide the desired return values.
For our scenario, we want to throw an SQL exception when the `executeUpdate` method of the prepared statement is called. We achieve this by using the `thenThrow` method and passing a new instance of `SQLException` with an appropriate error message.
The next step is to test the behavior of our code under these exceptional circumstances. In this case, we call the `updateData` method of our `DatabaseService` class, which internally interacts with the database using the mocked objects. We can then write assertions to validate the expected behavior of our code when the exception is thrown.
Now, let’s address some frequently asked questions about throwing SQL exceptions with Mockito:
Q: Can Mockito throw other types of exceptions?
A: Yes, Mockito can throw any type of exception, not just SQL exceptions. It allows you to simulate different scenarios by throwing exceptions of your choice when a specific method is called.
Q: Is it possible to throw exceptions from multiple method calls in a sequence?
A: Yes, Mockito provides capabilities to throw exceptions in a specific sequence. You can achieve this by chaining multiple `thenReturn` or `thenThrow` calls.
Q: Are there any limitations in throwing checked exceptions with Mockito?
A: Mockito has some limitations when it comes to throwing checked exceptions. If a method throws a checked exception, such as `SQLException`, it must be declared in the method signature. However, Mockito can still handle checked exceptions thrown by methods that are not declared in the signature, such as methods of mocked objects.
Q: Can I configure Mockito to throw different exceptions based on certain conditions?
A: Absolutely! Mockito provides the `thenAnswer` method, which allows you to define custom logic for throwing exceptions. You can use this method to throw different exceptions based on specific conditions or the input arguments of the method being called.
Q: Is it possible to throw exceptions only on specific invocations of a method?
A: Yes, Mockito provides a variety of matching mechanisms to define when an exception should be thrown. For example, you can use the `any` matcher to specify that an exception should be thrown regardless of the method arguments or use more specific matchers to control the throwing behavior.
In conclusion, Mockito is a powerful framework that allows us to throw SQL exceptions during unit testing. By using its mocking capabilities, we can simulate different database interaction scenarios and test the behavior of our code under exceptional circumstances. This not only ensures the correctness of our implementations but also helps in identifying potential issues that may occur during runtime. With the knowledge gained from this article, you should now be well-equipped to effectively use Mockito to test code that interacts with databases and handles SQL exceptions.
Images related to the topic checked exception is invalid for this method
Found 35 images related to checked exception is invalid for this method theme
Article link: checked exception is invalid for this method.
Learn more about the topic checked exception is invalid for this method.
- throw checked Exceptions from mocks with Mockito
- Checked and Unchecked Exceptions in Java | Baeldung
- Why mockito returning me MockitoException while I’m …
- throw checked Exceptions from mocks with Mockito – Intellipaat
- doThrow(), Wrong error message on final method (Checked …
- Checked vs Unchecked Exceptions in Java – GeeksforGeeks
- throw checked Exceptions from mocks with Mockito – Intellipaat
- How to Handle Checked & Unchecked Exceptions in Java
- Checked and Unchecked Exceptions in Java | Baeldung
- Exception Handling in Kotlin – Baeldung
- Unchecked Exceptions — The Controversy
- Mockito – Stubbing methods with exceptions – LogicBig
- How to Handle Checked & Unchecked Exceptions in Java
- Getting Checked exception is invalid for this method … – Reddit
See more: https://nhanvietluanvan.com/luat-hoc/