TS 74 Refactoring4

Refactoring 4

Author:Jiri Prox jiri.prox@oracle.com
Version:7.4
Last update:2013/07/25
Introduction:Replace constructor with factory, replace constructor with builder, invert boolean, introduce local extension, inline

Contents

Test suite: Replace constructor with factory

  1. Replace selected constructor
    1. Open factory.RplWithFactory class
    2. Put cursor at constructor at line 13
    3. Call Replace constructor with factory
    4. type new name of the factory method
    5. Confirm refactoring.
    • EXPECTED RESULT:The selected constructor is turned to private and the new static method is introduced, calling this private constructor. All calls of this constructor (in current class and in class User) are changed to static call of the new method. (6 occurrences are modified)
  2. Replace selected constructor call
    1. Undo any previous changes and open factory.RplWithFactory class again
    2. Put cursor at constructor call at line 20
    3. Call Replace constructor with factory
    4. Confirm refactoring
    • EXPECTED RESULT:The code is modified exactly at in the last test case
  3. Refactoring availability
    1. Open any java file
    2. Try putting cursor at some place in the file and calling Replace constructor with factory
    3. Try also selecting various nodes in project view
    • EXPECTED RESULT:The menu item is present and enabled only when cursor is in editor. When invoking refactoring on element which is not constructor or constructor call, a warning message is shown.
  4. Default constructor
    1. Open DefaultCtor.java
    2. Put cursor at constructor call at line 14
    3. Call Replace constructor with factory
    • EXPECTED RESULT:New private constructor and the factory method are introduced
  5. Subclass
    1. Open factory.RplWithFactory class
    2. Put cursor at constructor at line 16
    3. Call Replace constructor with factory
    • EXPECTED RESULT:The refactoring cannot continue, since there is call super(double) in the subclass
  6. Not public constructor
    1. Open NotPublic
    2. Call Replace constructor with factory for the class constructor
    • EXPECTED RESULT:The factory method is protected since the original constructor was protected as well. The constructor itself is turned to private
  7. Reference between constructors
    1. Open ThisCall
    2. Call Replace constructor with factory at the constructor at line 13
    • EXPECTED RESULT:The this() call in the second constructor is not changed
  8. InnerClass
    1. Open NestedClass
    2. Call Replace constructor with factory at the constructor at line 15
    • EXPECTED RESULT:There is warning that this refactoring cannot be performed in non-static inner class. Try turning the class into static and call the refactoring again. The refactoring should work then.
  9. Enum
    1. Open Enum
    2. Call Replace constructor with factory at line 15
    • EXPECTED RESULT:The refactoring cannot be performed in enums
  10. Name check
    1. Open RplWithFactory
    2. Call Replace constructor with factory at line 13
    3. Then call Replace constructor with factory again for the same constructor - in both cases keeps defaults
    • EXPECTED RESULT:There is warning that the method create() already exists
  11. Generics
    1. Open Generics
    2. Call Replace constructor with factory on the constructor
    • EXPECTED RESULT:The factory method takes one generic parameter. The constructor call is replaced by "Generics.<String>create();"

Test suite: Replace constructor with builder

  1. Refactoring Availability
    1. Open any file
    2. Try calling Replace constructor with builder on various elements of the code
    3. Try calling this refactoring also on various node typed in project view
    • EXPECTED RESULT:The refactoring is available enabled in menu only when focus is in editor. It can be called only on constructor or constructor call, otherwise there is warning Cannot refactor this element
  2. Basic Case
    1. Open RplWithBuilder.java
    2. Put cursor at constructor at line 13
    3. Call Replace Constructor With Builder
    4. Keep defaults, and press Refactor
    • EXPECTED RESULT:The refactor dialog is opened, there is table with separate row for each parameter, and text field for builder name. When refactoring is performed, the new class is introduced. It has filed and related setter method for each parameter (the setter returns this, so the setter calls can be chained). There is method createRplWithBuilder which calls the original constructor. The other constructor call are replaced with builder (new RplWithBuilderBuilder().setX(1).setY("").createRplWithBuilder();)
  3. Setter name
    1. Undo any previous changes
    2. Open RplWithBuilder.java and call refactoring for the constructor at line 13
    3. Change the setters named
    4. Perform refactoring
    • EXPECTED RESULT:The setters have correct names. The chained call is constructed correctly.
  4. Optional setter
    1. Undo any previous changes
    2. Open RplWithBuilder.java and call refactoring for the constructor at line 13
    3. Check Optional checkbox for each row
    4. Provide default value for each parameter
    5. Perform refactoring
    • EXPECTED RESULT:If the Optional checkbox is selected. the default value must be provided. (otherwise there is warning massage and refactoring cannot continue). The builder fields are initialized by default values. If the default value matches the actual valued the setter called is omitted. (e.g. it the default value for parameter x is 1, the creating new instance is "new RplWithBuilderBuilder().setY("").createRplWithBuilder();" )
  5. Builder Name
    1. Undo any previous changes
    2. Open RplWithBuilder.java and call refactoring for the constructor at line 13
    3. Change the builder name
    4. Perform refactoring
    • EXPECTED RESULT:The builder has correct name, and it it correctly used when creating new instances
  6. Builder Already Exists
    1. Repeat previous test case
    2. As the builder name type name of the existing class or invalid identifier
    • EXPECTED RESULT:The refactoring cannot continue, there is warning in the dialog
  7. Enum
    1. Open Enum.java
    2. Call refactoring on constructor
    • EXPECTED RESULT:There is waring that enum cannot be refactored, the refactoring cannot continue
  8. Abstract class
    1. Open AbsClass
    2. Call refactoring on the constructor
    • EXPECTED RESULT:There is waring that abstract class cannot be refactored, the refactoring cannot continue
  9. SubClass
    1. Open SubClass (undo any changes if the file was modified)
    2. Call refactoring for constructor at line 16
    3. Perform refactoring
    • EXPECTED RESULT:The builder is created. The super(double) call in the subclass constructor is not changed
  10. This call
    1. Open ThisCall
    2. Call refactoring for constructor at line 13
    3. Perform refactoring
    • EXPECTED RESULT:The call "this(int)" in the second constructor is not changed
  11. Implicit default constructor
    1. Open Default
    2. Call refactoring at constructor call at line 15
    3. Perform refactoring
    • EXPECTED RESULT:The builder without any fields are created. The line 15 is changed to "new DefaultBuilder().createDefault();"
  12. Varargs
    1. Open RplWithBuilder (undo any changes if the file was modified)
    2. Call refactoring for constructor at line 19
    3. Perform refactoring
    • EXPECTED RESULT:The builder is correctly generated and used
  13. Generics
    1. Open Generics
    2. Call refactoring for constructor at line 13
    • EXPECTED RESULT:The generics builder is created and is correctly used for creating instances

Test suite: Invert boolean

  1. Refactoring availability
    1. Open invert.Invert class
    2. Try calling Refactoring -> Inver Boolean on different places of the code
    3. Try calling Refactoring -> Inver Boolean in project view
    • EXPECTED RESULT:In project the Invert Boolean refactoring is disabled. In editor the refactoring can be called everywhere, but only on suitable places the refactoring dialog is opened. Otherwise the warning is displayed. The suitable places are declaration and body of methods returning boolean,return statements of this methods and methods calls
  2. Constant
    1. Open invert.Invert class
    2. Call Invert refactoring at line 17 or 18
    3. Keep defaults and confirm the dialog
    • EXPECTED RESULT: The constant in the return statement is changed to false. All calls of the method are prefixed with negation (!), so the code behaviour does not change
  3. Rename
    1. Open invert.Invert class
    2. Call Invert Boolean at line 17
    3. In the dialog, change the method name and confirm
    • EXPECTED RESULT:The boolean constant is inverted, as in previous case, and the method name and all method calls are replaced by the new name. Of course the calls are prefixed with negation
  4. Method call
    1. Open invert.Invert class
    2. Call Invert Boolean at line 62
    • EXPECTED RESULT:The method is changed as in previous cases
  5. Relation expression
    1. Open invert.Invert class
    2. Call Invert Boolean at line 21 and confirm
    • {{{1}}}
  6. Library method
    1. Open invert.Invert class
    2. Call Invert Boolean at line 26 and confirm
    • EXPECTED RESULT:
  7. Local variable
    1. Open invert.Invert class
    2. Call Invert Boolean at line 29 and confirm
    • EXPECTED RESULT:The expression in the return statement and the method calls are negated
  8. Static method
    1. Open invert.Invert class
    2. Call Invert Boolean at line 35 and confirm
    • EXPECTED RESULT:The argument of return statement is correctly negated. The method calls are negated
  9. Overriding method
    1. Open invert.Invert class
    2. Call Invert Boolean at line 39 and confirm
    • EXPECTED RESULT:Refactoring cannot be performed
  10. Negation of negation
    1. Open invert.Invert class
    2. Call Invert Boolean at line 43 and confirm
    • EXPECTED RESULT:The negation is removed from the argument of return statement
  11. Complex expression
    1. Open invert.Invert class
    2. Call Invert Boolean at line 47 and confirm
    • EXPECTED RESULT:The return expression is changed from the !x
  12. Autoboxing
    1. Open invert.Invert class
    2. Call Invert Boolean at line 51 and confirm
    • EXPECTED RESULT:The Boolean.TRUE is correctly changed to Boolean.FALSE
  13. Annotation
    1. Open invert.Invert class
    2. Call Invert Boolean at isOK at line 60 and confirm
    • EXPECTED RESULT:The call of isOK at line 75 is negated, the default value in the annotation declaration is changed to 'false' and the actual value (at line 60) is also changed to 'false'
  14. More Return Statements
    1. Open invert.Invert class
    2. Call Invert Boolean at line 55 and confirm
    • EXPECTED RESULT:All return statements are correctly negated

Test suite: Introduce local extension

Comments: In Introduce Local Extension dialog keep default unless in the testcase there is explicitly written different value. After each test case undo all changes

  1. Introduce Local Extension as Wrapper
    1. Open LocalExtension.java
    2. Put cursor at class definition and call Introduce Local Extension
    3. In the dialog keep default new name, select Type=Wrapper and Equality=Delegate, select Replace original usages with the extension
    4. Perform refactoring
    • EXPECTED RESULT:New class LocalExtenstion1 is introduced. It has field LocalExtenstion delegate. All method and fields (field and method) of original class are accessed through it. There are two constructor, on has int parameter (as original class) the second has LocalExtenstion argument. The hashCode and equals methods are created. hashCode only delegates to original class. Equals returns this.delegate.equals(target) where target is either original argument of equals or delegate if original argument of equals was instance of LocalExtension1. All occurrences of LocalExtenstion are replaced by LocalExtension1 (see Usages class)
  2. Introduce Local Extension as Subtype
    1. Open LocalExtension.java
    2. Put cursor at class definition and call Introduce Local Extension
    3. In the dialog keep default new name, select Type=Subtype and Equality=Delegate, select Replace original usages with the extension
    4. Perform refactoring
    • EXPECTED RESULT:When selectingh 'Subtype' the 'Equality' radio button is disabled. When refactoring is performed a new class LocalExtension1 is introduced, it is subtype of LocalExtension, all occurrences of original class are replaced by newly introduced class
  3. Equality - generate
    1. Repeat the first test case, but in refactoring dialog select Equality=Generate
    2. Perform refactoring
    • EXPECTED RESULT:A new class is introduced and all occurrences are replaced as in first test case. Body of equals and hashCode method now looks like it was generate by Generate Code feature
  @Override
   public boolean equals(Object obj) {
       if (obj == null) {
           return false;
       }
       if (getClass() != obj.getClass()) {
           return false;
       }
       final LocalExtension1 other = (LocalExtension1) obj;
       if (!Objects.equals(this.delegate, other.delegate)) {
           return false;
       }
       return true;
   }
   @Override
   public int hashCode() {
       int hash = 7;
       hash = 79 * hash + Objects.hashCode(this.delegate);
       return hash;
   }
  1. Equality - Separate
    1. Repeat the first test case, but in refactoring dialog select Equality=Separate
    2. Perform refactoring
    • EXPECTED RESULT:A new class is introduced and all occurrences are replaced as in first test case. Body of equals and hashCode methods are same as in the first case, but now there is one more method equalsLocalExtension1 which directly calls equals from wrapped class
  2. Replace Original Usages
    1. Repeat the first test case, but in refactoring dialog unselect Replace original usages with the extension
    2. Perform refactoring
    • EXPECTED RESULT:The new class is introduced, but usages of old class are not changed
  3. Package Private Elements
    1. Open LePackagePrivate.java
    2. Introduce Local Extension of this class
    3. In the dialog select Type=Wrapper' and Equality=Delegate, select Replace original usages with the extension, in To package type new package
    4. Perform refactoring
    • EXPECTED RESULT:There is warning that introduced class may not access some of the elements from original class
  4. Inner Classes
    1. Open LEInnerClasses.java
    2. Call Introduce Local Extension, select Type=Wrapper and Equality=Delegate, select Replace original usages with the extension
    3. Perform refactoring
    • EXPECTED RESULT:The usages of inner classes of original classes are not updated, since the inner classes are not moved to introduced class
  5. Interfaces, Annotation, Enums
    1. Open LEOtherTypes.java
    2. Try invoke Introduce Local Extension on enum, interface and annotation
    • EXPECTED RESULT:Refactoring of this elements is not allowed
  6. Implements, Extends
    1. Open ExtendsImplements.java
    2. Introduce Local Extension as a wrapper
    • EXPECTED RESULT:All implemented interface are copied to newly created class (Readable, Closeable), the classes which the original class extends are not used
  7. Generics
    1. Open Generics.java
    2. Introduce Local Extension as a wrapper
    • EXPECTED RESULT:New Generics1<T> class is introduced
  8. Generic in Extends
    1. Open ExtendsGeneric.java
    2. Introduce Local Extension as a wrapper
    • EXPECTED RESULT:A new class is introduced, the usages of generic type are correctly resolved
  9. Extending Inner static class
    1. Open Wrapper
    2. Introduce local extension of the Inner class
    • EXPECTED RESULT:The new class is correctly created

Test suite: Inline

Purpose: This test suite describes Inline Refactoring

  1. Refactoring availability
    1. Open Inline.java
    2. Try putting cursor on various elements and calling Refactoring -> Inline
    3. Try invoking Inline also from navigator
    • EXPECTED RESULT:The refactoring Inline can be called only on methods, fields and local variables (declaration or usage). In this case the refactoring preview is automatically opened. Otherwise the dialog appears saying that refactoring is not suitable for that type of element
  2. Inline method
    1. Open Inline.java
    2. Put cursor on method add(int,int) and call inline
    3. Confirm refactoring
    • {{{1}}}
  3. Return value is not used
    1. Open Inline.java
    2. Put cursor on method sub(int,int) and call inline
    • EXPECTED RESULT:There is warning that the return value is not used (e.g. the refactoring may not work correctly)
  4. More return statements
    1. Open Inline.java
    2. Put cursor on method max(int,int) and call inline
    • EXPECTED RESULT:Warning appears, inline cannot be called on method with more return statements
  5. Local variables and multiple invocation
    1. Open Inline.java
    2. Put cursor on method mul(int,int) and call inline
    3. Perform refactoring
    • EXPECTED RESULT:The body of method is copied at each method call. The method local variable is suffixed with number, in order to avoid multiple same declaration and to avoid conflict with local variables (in this case, variable result is transformed to result1 and result2)
  6. Inlined method is argument
    1. Open Inline.java
    2. Put cursor on method div(int,int) and call inline
    3. Perform, refactoring
    • EXPECTED RESULT:The method body is copied to proper place, the original method call is substituted with expression in return statement.
  7. Nested method call
    1. Open Inline.java
    2. Put cursor on method concat(String,String) and call inline
    3. Perform refactoring
    • EXPECTED RESULT:The nested method call is correctly inlined
  8. Recursive method
    1. Open Inline.java
    2. Put cursor on method fact(int) and call inline
    3. Perform refactoring
    • EXPECTED RESULT:Recursive method cannot be inlined
  9. Chained method call
    1. Open Inline.java
    2. Put cursor on method numbers(int) and call inline
    • EXPECTED RESULT:The method is correctly inlined
  10. Method from interface
    1. Open Inline.java
    2. Put cursor on method m() at line annot.m() and call Inline
    3. Put cursor on method xxx() at line a.xxx() and call Inline
    • EXPECTED RESULT:In both cases, there is waring that interface method cannot be inlined
  11. Abstract method
    1. Open Inline.java
    2. Put cursor on method absMethod() and call Inline
    • EXPECTED RESULT:The waring that abstract method cannot be inlined is shown, refactoring cannot continue
  12. Constructor
    1. Open Inline.java
    2. Call Inline on constructor
    • EXPECTED RESULT:The constructor cannot be inlined
  13. Library class
    1. Open Inline.java
    2. Call inline on println method
    • EXPECTED RESULT:Methods from library classes cannot be inlined
  14. Inline Constant
    1. Open InlineField.java
    2. Put cursor at CONST
    3. Call inline
    • EXPECTED RESULT:The constant is correctly inlined. All occurrences are replaced by value
  15. Inline Local Variable
    1. Open InlineField.java
    2. Put cursor at localVariable and call Inline
    • EXPECTED RESULT:Local variable is inlined, all occurrences are replaced with it's value
  16. Inline may change behavior
    1. Open InlineField.java
    2. Put cursor at local variable xx and call Inline
    • EXPECTED RESULT:There should be warning that refactoring may change code behavior. When proceeding with Inline, all occurrences of xx are replaced with new String("")
  17. Invalid cases
    1. Open InlineField.java
    2. Put cursor at Enn.A' and call Inline
    3. Put cursor at parameter a and call Inline
    4. Put cursor at fr in try statement and call Inline
    5. Put cursor at ex in catch statement and call Inline
    • EXPECTED RESULT:In all cases there is dialog that refactoring cannot be invoked on this type of element. Inline cannot be performed
Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo