Testování privátních metod

V některých případech obsahuje třída složité metody, které však používá pouze tato třída a je zbytečné měnit jejich viditelnost jen kvůli otestování. K otestování takových metod je nutné využít reflexi.

Třída, kterou budeme testovat. Tato třída obsahuje veřejnou metodu compute() a privátní metodu getLongFromString(). Obě tyto metody budeme chtít otestovat.

public class MyClass {
    
    public long compute(String num1, String num2) {
          return Math.abs(getLongFromString(num1) - getLongFromString(num2));
    }

    private long getLongFromString(String number) {
          return Long.parseLong(number);
    }
}

Třída, která slouží jako předek všech testovacích tříd. Tato třída obsahuje metodu getPrivateMethods, která na základě třídy, názvu metody a jejich parametrů dokáže vrátit a zpřístupnit danou metodu na daném objektu.

import java.lang.reflect.Method;

public class AbstractTest {
 
       protected Method getPrivateMethod(Class<?> clazz, String methodName, Class<?> ... parameterTypes) {
             try {
                    // get method vrací pouze public metody
                    // Method method = clazz.getMethod(methodName, parameterTypes);
                    // proto je potřeba volat getDeclaredMethod
                    Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
                    method.setAccessible(true);
                    return method;
             } catch (Exception e) {
                    throw new IllegalArgumentException("Cannot obtain method with name: " + methodName, e);
             }
       }
}

A nakonec třída s testy. Metodu getLongFromString testujeme dvakrát. Jednou pro případ, že zadáme správné parametry a podruhé testujeme, že vyhodí výjimku.

import static org.junit.Assert.assertTrue;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
import org.junit.BeforeClass;
import org.junit.Test;
 
public class MyClassTest extends AbstractTest {
       private static MyClass myClass;
      
       @BeforeClass
       public static void prepare() {
             myClass = new MyClass();
       }
 
       @Test
       public void computeOK() {
             String n1 = "120";
             String n2 = "330";
            
             long result = myClass.compute(n1, n2);
             assertTrue(result == 210);
       }
      
       @Test
       public void getLongFromStringOK() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
             String n = "30";
            
             Method testedMethod = getPrivateMethod(MyClass.class, "getLongFromString", String.class);
             long result = (Long) testedMethod.invoke(myClass, n);
            
             assertTrue(result == 30);
       }
      
       @Test(expected = InvocationTargetException.class)
       public void getLongFromStringThrowsException() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
             String s = "AB";
            
             Method testedMethod = getPrivateMethod(MyClass.class, "getLongFromString", String.class);
             testedMethod.invoke(myClass, s);
       }
      
}

Anotace @BeforeClass znamená, že daná metoda se volá jednou a to před voláním jakékoliv jiné metody ve třídě. Anotace @Test(expected = InvocationTargetException.class) definuje, jaký typ výjimky má být vyhozen. Metoda getLongFromString sice vyhodí NumberFormatException, ale ta pak způsobí InvocationTargetException. Z toho důvodu očekáváme při testu tuto výjimku.

Vytvoření řetězce z pole stringů

Níže uvedený kód předpokládá, že máme definováno následující pole: String[] arr = {"a", "b", "c", "d"}.

Použití StringBuilderu.

StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
       sb.append(arr[i]);
       if (i < arr.length - 1) {
              sb.append(", ");
       }
}
System.out.println(sb.toString());

Variace na předchozí způsob.

StringBuilder sbb = new StringBuilder();
for (int i = 0; i < arr.length; i++) { 
       if (i > 0) {
              sbb.append(", ");
       }
       sbb.append(arr[i]);
}
System.out.println(sbb.toString());

Použití StringUtils (vnitřně používá StringBuilder).

String result = StringUtils.join(arr, ", ");
System.out.println(result);

Do projektu je třeba přidat závislost.

<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.4</version>
</dependency>

A trochu divoký způsob pomocí třídy Arrays a regulárních výrazů.

String string = Arrays.toString(arr);
String regex = Pattern.quote("[") + "|" + Pattern.quote("]");
String string2 = string.replaceAll(regex, "");
System.out.println(string2);

Převede pole na řetězec (ten obsahuje [] a jednotlivé stringy oddělené čárkou). Následně provede odstranění hranatých závorek. Pattern.quote() provádí správně odescapování daného znaku či sekvence znaků.

Rozdíl mezi lambda a anonymní třídou

Lambda výraz je jiný způsob zápisu anonymních tříd v Javě.

Lambda

Arrays.sort(pole, (String first, String second) -> {
	return Integer.compare(first.length(), second.length());
});

Anonymní třída

Arrays.sort(pole, new Comparator() {
	@Override
	public int compare(String first, String second) {
		return Integer.compare(first.length(), second.length());
	}
});

Lambda výraz je možné použít proto, že Comparator je funkční rozhraní. To znamená, že toto rozhraní má jedinou abstraktní metodu. Pro tato rozhraní se používá anotace @FunctionalInterface. Tato anotace není povinná a pouze kontroluje, zda dané rozhraní splňuje podmínky funkčního rozhraní.

Problém s lambda v Eclipse

Pokud používáte pro vývoj v Javě Eclipse IDE a chcete vyzkoušet psaní lambda výrazů, což je novinka v Javě 8, může se stát, že Eclipse vám validní lambda kód označí jako chybu a to i přesto, že Java 8 máte nainstalovanou a přidanou do build path. Je totiž ještě nutné nastavit compiler compliance level: Window -> Preferences -> Java -> Compiler -> vybrat „Compiler compliance level“ 1.8 -> potvrdit.

Eclipe_ide_compliance_level

Pokud ani toto nepomohlo zkontrolujte nastavení projektu: pravým na projekt -> Properties -> Java Compiler -> vybrat „Compiler compliance level“ 1.8 -> potvrdit.

Nápověda při psaní v Eclipse IDE

Pokud v Eclipse píšete kód, defaultně se nezobrazuje nápověda pro výběr. Je potřeba stisknout Ctrl a mezerník a teprve pak se obsahová nápověda zobrazí. V IntelliJ Idea IDE se rovnou při psaní nápověda, po napsání několika znaků, zobrazí.

Následující změna v nastavení Eclipse umožní automatické zobrazení kontextové nápovědy při psaní: Window -> Preferences -> Java -> Editor -> Content Assist -> v sekci „Auto Activation“ zaškrtněte „Enable auto activation“ a do „Auto activation triggers for Java:“ zadejte řetězec ._abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ a změny potvrďte.

Eclipse_content_assist

Zdroj: www.stackoverflow.com

Make, no error check v Idea IDE

V případě, že v Eclipse IDE chcete spustit main metodu v projektu, který obsahuje chyby (celý projekt nelze zkompilovat), Eclipse vás na to upozorní a zeptá se, zda chcete pokračovat. Pokud potvrdíte, že ano, zkusí pokračovat. Pokud ve spouštěné metodě a použitých třídách nemáte chybu, metoda se úspěšně spustí a vykoná.

V IntelliJ Idea IDE je tomu jinak. V případě, že projekt obsahuje chybu, nespustí se. Toto chování lze změnit: Run -> Edit Configurations … -> otevře se okno Run/Debug Configurations ->  v části „Before launch“ klikněte na plus a zvolte „Make, no error check“ -> odstraňte původní „Make“ -> OK.

Intellij_Idea_make_no_error

Zdroj: www.stackoverflow.com

Ve výše zmíněné odpovědi na Stackoverflow je uvedena i možnost změny compileru na Eclipse compiler. Tento postup mi nefungoval. Vždy bylo ještě potřeba změnit Run/Debug Configuration na „Make, no error check“.

Rozšíření funkčnosti editoru ve WordPressu

Editor článků a příspěvků TinyMCE je dostatečný, avšak časem určitě narazíte na funkcionality, které mu chybí. U mě to byla chybějící volba pro přidání tabulky. Editor tuto možnost má, ale defaultně není zobrazena. Jedním z řešení je instalace TinyMCE Advanced pluginu, který tyto volby zpřístupní.

tinymce_advanced

Následujícím způsobem pak po instalaci pluginu bude vypadat menu TinyMCE editoru.

tinymce_advanced02

Řešení jsem našel na tomto webu: www.mujitblog.cz

Přihlášení do Windows 10 bez zadání hesla

V případě, že nechcete při každém spuštění počítače s Window 10 zadávat přihlašovací údaje, můžete si nastavit automatické přihlašování. Klikněte na lupu („Prohledat Windows“) v levé části panelu nástrojů a do ní zadejte netplwiz  a spusťte příkaz (netplwiz.exe je umístěn v adresáři C:\Windows\System32 a slouží pro spravování uživatelských účtů).

lupa

Otevře se vám okno „Uživatelské účty“. V něm zrušte volbu pro zadávání přihlašovacích údajů a potvrďte.

uzivatelske_ucty

Po potvrzení se otevře další okno, kde zadáte uživatele, který bude automaticky přihlášen.

Pozor, tento postup mi nefungoval v případě, že jsem se snažil přihlásit účtem Microsoft. Je nutné se přihlašovat místním účtem. Klikněte na lupu a napište uživatelské účty . Otevře se vám okno „Uživatelské účty“. V něm klikněte na „Provést změny mého účtu v nastavení počítače“. Zde si vytvořte místní účet a nastavte přihlašování pomocí místního účtu.