Unit testy s knihovnou EasyMock

21. October 2008

Možná jsem někde zaspal, ale knihovnu EasyMock jsem začal používat teprve nedávno u nás ve firmě. Jeho schopnosti a snadnost použití jsou tak výrazné, že rozhodně stojí za představení.

K čemu je to vlastně dobré

EasyMock je pomocník pro psaní unit testů. Unit testy slouží k otestování jedné třídy. Nezajímají nás objekty, se kterými testovaná třída spolupracuje. Buď věříme tomu, že fungují správně…a nebo tyto závislosti namockujeme.

Namocková je nahrazení skutečných spolupracujících tříd tzv mocky. Mock je proxy implementující určitý interface. U této proxy máme možnost nadefinovat její chování programově pomocí API.

Jak to funguje

  1. Vytvoříte mock objekt (1. řádek kódu)
  2. Nadefinujete jeho chování (včetně návratových typů a výjímek)
  3. Nadefinujete požadované volání metod (EasyMock kontroluje i jejich pořadí)
  4. Přepnete se do přehrávací fáze
  5. Spustíte vlastní unit test
  6. EasyMock za vás ověří, že byly splněny všechny podmínky nadefinované v bodě 2 a 3

EasyMock se velmi hodí tam, kde používáte návrhový vzor IoC a potřebujete otestovat beanu, která potřebuje mít nasetované reference na ostatní beany. Ideálně, když referencované beany jsou interfacy (EasyMock umí mockovat pomocí rozšížení i classy). Pomocí EasyMocku si tedy vytvoříte přislušné mocky, nahrajete jejich chování. Zavoláte testovanou metodu a Easymock zkontroluje, zda všechno proběhlo podle vašich požadavků.

Malá ukázka testu z příkladu (EasyMockDemo­.zip, ZIP 260 KB): .

public class TestServiceImplTest extends TestCase {
        private TestServiceImpl testServiceImpl;
        private TestDao testDao;

        public void test_getBeanById_ok() throws Exception {
                Bean bean1 = new Bean();
                bean1.setId(1);

                EasyMock.expect(testDao.getBeanById(1)).andReturn(bean1);

                replay();

                Bean bean = testServiceImpl.getBeanById(1);
                assertEquals(1, bean.getId());

                verify();
        }

        public void test_getBeanById_null_returned() throws Exception {
                EasyMock.expect(testDao.getBeanById(1)).andReturn(null);

                replay();

                Bean bean = testServiceImpl.getBeanById(1);
                assertNull(bean);

                verify();
        }

        public void test_getBeanById_exception_thrown() throws Exception {
                Bean bean1 = new Bean();
                bean1.setId(1);

                EasyMock.expect(testDao.getBeanById(1)).andThrow(new DaoException("Some DAO exception"));

                replay();

                try {
                        testServiceImpl.getBeanById(1);
                        fail();
                } catch (ServiceException e) {

                }

                verify();
        }

        protected void replay() {
                EasyMock.replay(testDao);
        }

        protected void verify() {
                EasyMock.verify(testDao);
        }

        @Override
        protected void setUp() throws Exception {
                super.setUp();
                testServiceImpl = new TestServiceImpl();
                testDao = EasyMock.createMock(TestDao.class);
                testServiceImpl.setTestDao(testDao);
        }

        @Override
        protected void tearDown() throws Exception {
                super.tearDown();
                testServiceImpl = null;
                testDao = null;
        }
}

Závěr

Bez mock testů si dnes unit testy už nedovedu představit.

Odkazy

Článek patří do kategorie: Testování aplikací

3 Komentářů Přidat komentář

  • 1. benzin  |  22. October 2008 v 13.38

    No ano bez mocku se ani snad testovan neda, jenom si davejte opravdu pozor. Protoze EasyMock netestuje spravnost implementace, ale pouze ze byla nejak jina trida zavolana, v jakem poradi a s jakymi parametry.

    A v tom je prave onen kamen urazu. Pri zmene interface se vam muze rozbit spousta testu, a dat je do kupy neni snadne.

    Navis vas EasyMock nuti testovat neco co testovat ani nechcete. Dejme tomu HttpRequest, aktualne nase metoda vola getContextPath(), toto volani ale ve skutecnosti neni pro funkci vubec podstatne (dejme tomu ze se pouziva v logovani). Bohuzel do EasyMocku to nacpat musite. V pripade ze pak nekdo prestane logovat (a to muze prestat nekde hluboko v kodu, nebo zapne jinou logovaci uroven), tak najednou neprojde test.

    Tak EasyMock pouzivejte s mirou, ne vzdy je totiz zjevne proc je toto volani tak dulezit a proc v tomto poradi a proc tolikrat….

  • 2. tomas  |  23. October 2008 v 17.38

    Neda mi neupozornit na kniznicu http://www.uni­tils.org/, ktora znacne zjednodusuje pracu s EasyMock.

  • 3. david  |  3. November 2008 v 14.42

    to benzin: je pravda, ze napsat vsechny exceptation pro vsechny volane metody (i ty u kterych nepovazuju za dulezite kdy a kolikrat budou volany) neni moc efektivni. Ja to resim tak, ze nepouziju primo mock tridu, ale tridu od ni odvocenou, kde „nedulezite metody“ maji implementaci napr vracejici konstantni hodnotu.

    Moc_HttpRequest request = new Mock_HttpRequest()
    {
    @Override
    pulbic String getContextPath()
    {
    return CONSTANT_PATH;
    }
    };

Přidat komentář

Povinné

Povinné, skryté

Security Image Povinné
Opište text z obrázku

Povolené HTML značky:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

Odkazovat na tento článek  |  Přihlásit se k odběru těchto komentářů přes RSS Feed


Kalendář

October 2017
M T W T F S S
« Jan    
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

Poslední články

Locations of visitors to this page