[JAVA] Change variable values in debug without source changes or breaks (using conditional breakpoints)

What do you guys do when you want to test a route that you wouldn't normally go through after writing a program? Generally, I think that it is executed in the following form.

--Set breakpoints at specific locations --Perform the action you want to test --Wait to stop at a breakpoint --When you reach a breakpoint, change the value manually

However, there are times when you want to repeat the operation several times with the value changed, and in such a case, you want the value to be rewritten automatically. Have you ever thought?

Actually, this can be achieved by using conditional breakpoints, but I will leave it because many veterans do not know it.

Prerequisites and background

Sample code and assumed pattern

A method that executes RestAPI and performs state check → parse → model transformation. (The content is not particularly important)

    public JmaFeed getFeed() {
        ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);
        if (!response.hasBody()) {
            return null;
        }

        String responseBody = response.getBody();
        if (isNull(responseBody)) {
            return null;
        }

        JmaXmlFeed xml = xmlParser.read(response.getBody(), JmaXmlFeed.class);
        if (isNull(xml.getTitle())) {
            return null;
        }

        return modelMapper.map(xml, JmaFeed.class);
    }

This method can't usually happen

  1. isNull(responseBody)
  2. isNull(xml.getTitle())

Suppose you want to check the condition that becomes. Note that the value of xml.getTitle () can be rewritten with xml.setTitle (), and the source code must not be changed.

Background: Conditional breakpoints

When debugging with the IDE, you can set conditions for breakpoints. This is also called a ** conditional breakpoint **.

■ Screen when right-clicking at a breakpoint in IntelliJ

image.png


The usual usage of this condition is to set "when variable A is 0" or "when variable B is null". In other words, write as follows.

■ Example: Break when the variable responseBody is null image.png

Now you can stop at a breakpoint when responseBody = null.

How to change the value of a variable when debugging without source changes or breaks

Here is the main issue. I will explain two methods.

Assign to a variable value at a conditional breakpoint

The condition of the conditional breakpoint should finally return true / false, and anything can be done on the way. Therefore, it is possible to set such conditions.

conditions


(responseBody = null) != null

image.png

As you can see, this formula

--Substitute null for responseBody --Determine that responseBody is not null

The condition is always false and there is no break. In other words, it was possible to automatically rewrite the responseBody without stopping at the breakpoint.

Call setter with conditional breakpoints

Next, there is a method that satisfies the condition ʻisNull (xml.getTitle ()))of 2., but it requires more ingenuity than before. This is because in this program you can change the value withxml.setTitle (null), but many setters are void methods. This means that the method result cannot be compared to anything and expressions like xml.setTitle (null)! = Null` cannot be conditioned.

Therefore, try the following formula.

conditions


Optional.of("a").map(x -> { xml.setTitle(null); return false; }).get()

As a method of returning false while executing xml.setTitle (null), it was realized by using ʻOptional # map` which can take a method as an argument. If you can take a lambda expression as an argument and return an arbitrary value, I think that it can be realized by other methods.

By the way, in the case of Eclipse, just setting xml.setTitile (null) will rewrite the value as expected. It seems that the conditions differ depending on the IDE, so please check the behavior of the IDE you are using.

Summary

Here is a summary of how to change the value of a variable without breaking when debugging.

** 1. Assign to a variable value at a conditional breakpoint **

Substitute and write a condition that is false

Condition example


(responseBody = null) != null

** 2. Call setter with conditional breakpoint **

Call setter with Optional # map and return false

conditions


Optional.of("a").map(x -> { xml.setTitle(null); return false; }).get()

I think the same thing can be done in other languages by using the same mechanism.

Recommended Posts

Change variable values in debug without source changes or breaks (using conditional breakpoints)