Вызов метода юнит-тестирования (метод шаблона)? - PullRequest
1 голос
/ 03 декабря 2010

Можно ли вызвать метод юнит-теста для того же класса (по порядку и сколько раз они были вызваны)?

т.е. метод шаблона, подобный приведенному ниже:

    abstract class FooBarBaz {

       public abstract void foo();
       public abstract void bar();
       public abstract void baz();

       // I want to create a unit test for this method, in the following order
       public myTemplateMethod() {
          foo();  // i want to check foo first;
          bar();  // i want to check bar second;
          baz();  // i want to check baz third;
       }
    }

РЕДАКТИРОВАТЬ - Реализация встроенного кода мокито

import junit.framework.TestCase;
import org.mockito.Mockito;

public class FooBarBazTest extends TestCase {

   public void testMyTemplateMethodWithMockito() {
      FooBarBaz mocked = Mockito.mock(FooBarBaz.class);

      mocked.myTemplateMethod();

      Mockito.verify(mocked, Mockito.times(1)).foo();
      Mockito.verify(mocked, Mockito.times(1)).bar();
      Mockito.verify(mocked, Mockito.times(1)).baz();
   }
}

РЕДАКТИРОВАТЬ - Добавлена ​​трассировка стека

testMyTemplateMethodWithMockito(sample.FooBarBazTest)  Time elapsed: 0.326 sec  <<< FAILURE!
Wanted but not invoked:
fooBarBaz.foo();
-> at sample.FooBarBazTest.testMyTemplateMethodWithMockito(FooBarBazTest.java:14)

However, there were other interactions with this mock:
-> at sample.FooBarBazTest.testMyTemplateMethodWithMockito(FooBarBazTest.java:12)

    at sample.FooBarBazTest.testMyTemplateMethodWithMockito(FooBarBazTest.java:14)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at junit.framework.TestCase.runTest(TestCase.java:168)
    at junit.framework.TestCase.runBare(TestCase.java:134)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:124)
    at junit.framework.TestSuite.runTest(TestSuite.java:232)
    at junit.framework.TestSuite.run(TestSuite.java:227)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:59)
    at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:115)
    at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:102)
    at org.apache.maven.surefire.Surefire.run(Surefire.java:180)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)
    at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)

Ответы [ 2 ]

4 голосов
/ 03 декабря 2010

Взгляните на Mockito , в котором встроено это поведение.

Из их документации:
6. Проверка в порядке

 List firstMock = mock(List.class);
 List secondMock = mock(List.class);

 //using mocks
 firstMock.add("was called first");
 secondMock.add("was called second");

 //create inOrder object passing any mocks that need to be verified in order
 InOrder inOrder = inOrder(firstMock, secondMock);

 //following will make sure that firstMock was called before secondMock
 inOrder.verify(firstMock).add("was called first");
 inOrder.verify(secondMock).add("was called second");

А:
4. Проверка точного количества вызовов / не менее x / никогда

 //using mock 
 mockedList.add("once");

 mockedList.add("twice");
 mockedList.add("twice");

 mockedList.add("three times");
 mockedList.add("three times");
 mockedList.add("three times");

 //following two verifications work exactly the same - times(1) is used by default
 verify(mockedList).add("once");
 verify(mockedList, times(1)).add("once");

 //exact number of invocations verification
 verify(mockedList, times(2)).add("twice");
 verify(mockedList, times(3)).add("three times");

 //verification using never(). never() is an alias to times(0)
 verify(mockedList, never()).add("never happened");

 //verification using atLeast()/atMost()
 verify(mockedList, atLeastOnce()).add("three times");
 verify(mockedList, atLeast(2)).add("five times");
 verify(mockedList, atMost(5)).add("three times");
2 голосов
/ 03 декабря 2010

Использование моделирующей среды хорошо, но если вы не хотите полагаться на внешние зависимости, просто создайте тестовый класс, который реализует ваш абстрактный класс. Пусть абстрактные реализации метода foo, bar, baz добавят строки «foo», «bar», «baz» в общий список, а затем в своем тестовом методе просто подтвердите, что они находятся в списке в правильном порядке.

РЕДАКТИРОВАТЬ - я написал тесты как с mockito, так и без mockito. Они оба проходят - я раньше не использовал mockito, я мог бы попробовать его ...

import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

public class FooBarBazTests extends TestCase {


    @Test
    public void testMyTemplateMethod() {
        List tracker = new ArrayList();
        SimpleFooBarBaz toTest = new SimpleFooBarBaz(tracker);

        toTest.myTemplateMethod();


        assertEquals("foo", tracker.get(0));

        // more assertions
    }


    @Test
    public void testMyTemplateMethodWithMockito() {
        FooBarBaz mocked = mock(FooBarBaz.class);

        mocked.myTemplateMethod();

        // times(1) is unnecessary, but explicit
        verify(mocked, times(1)).foo();
        verify(mocked, times(1)).bar();
        verify(mocked, times(1)).baz();
    }

    class SimpleFooBarBaz extends FooBarBaz {


        List tracker;

        SimpleFooBarBaz(List tracker) {
            this.tracker = tracker;
        }

        public void foo() {
            tracker.add("foo");
        }

        @Override
        public void bar() {
            //To change body of implemented methods use File | Settings | File Templates.
        }

        @Override
        public void baz() {
            //To change body of implemented methods use File | Settings | File Templates.
        }

        // others there

    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...