Ответ 1
Вы бросаете IllegalArgumentException
и ловите IllegalStateException
. Вы можете добавить еще один блок catch с catch Exception
- он будет работать.
У меня есть следующее действие, которое генерирует исключение, если что-то настроено неправильно.
public class MyActivity extends AppCompatActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
throw new IllegalStateException("something went wrong");
}
}
Я попытался написать тест для этого ActivityInstrumentationTestCase2
public void testException() throws Exception {
try {
getActivity().onCreate(null);
fail();
} catch (IllegalStateException e) {
assertThat(e.getMessage()).contains("something went wrong");
}
}
который выдает правильный Exception
, но не работает в моем блоке catch
из-за некоторого внутреннего Sandboxing
ActivityInstrumentationTestCase2
.
Итак, я попробовал это с простой Java
public void testException() throws Exception {
final MockNavigationDrawerActivity activity = Mockito.mock(MockNavigationDrawerActivity.class);
Mockito.doCallRealMethod().when(activity).onCreate(null);
try {
activity.onCreate(null);
fail();
} catch (IllegalStateException e) {
assertThat(e.getMessage()).contains("something went wrong");
}
}
который не работает
java.lang.AbstractMethodError: abstract method "boolean org.mockito.internal.invocation.AbstractAwareMethod.isAbstract()"
at org.mockito.internal.invocation.InvocationImpl.callRealMethod(InvocationImpl.java:109)
at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:41)
at org.mockito.internal.stubbing.StubbedInvocationMatcher.answer(StubbedInvocationMatcher.java:34)
at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:91)
at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:38)
at com.google.dexmaker.mockito.InvocationHandlerAdapter.invoke(InvocationHandlerAdapter.java:49)
at MockNavigationDrawerActivity_Proxy.onCreate(MockNavigationDrawerActivity_Proxy.generated)
Любая идея, как протестировать этот простой случай?
Я пробовал абсолютно все. Я уменьшил его до абсолютного минимума, который не работает.
public void testUpdate1() throws Exception {
try {
getActivity();
fail();
} catch (Exception e) {
assertThat(e.getMessage()).contains("something went wrong");
}
}
StackTrace:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.MyActivity}: java.lang.IllegalStateException: something went wrong
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.IllegalStateException: something went wrong
at com.example.MyActivity.onCreate(MyActivity.java:28)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.support.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:346)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
... 10 more
Я начал с самого начала. Создал новый проект, выбросил Exception
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
throw new IllegalStateException("something");
}
a попытался поймать его с помощью Throwable
.
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
public MainActivityTest() {
super(MainActivity.class);
}
public void testOnCreate() throws Exception {
try {
getActivity();
fail();
} catch (Throwable throwable) {
assertTrue(throwable.getCause().getMessage().contains("something"));
}
}
}
Я получил эту (полную) стек, которая не приводит к моему тесту. Кажется, система вызывает onCreate
, возможно, из другого процесса, а не моего теста.
Process: com.pascalwelsch.onccreatetest, PID: 3915 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pascalwelsch.onccreatetest/com.pascalwelsch.onccreatetest.MainActivity}: java.lang.IllegalStateException: something
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.IllegalStateException: something
at com.pascalwelsch.onccreatetest.MainActivity.onCreate(MainActivity.java:15)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
at android.app.ActivityThread.access$800(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
Вы бросаете IllegalArgumentException
и ловите IllegalStateException
. Вы можете добавить еще один блок catch с catch Exception
- он будет работать.
Почему вы издеваетесь над классом, который вы пытаетесь проверить? Вы должны издеваться над зависимостями MyActivity
, чтобы проверить правильность его методов с помощью mocks.
Например, если вы хотите протестировать класс A
, который зависит от B
и C
, то вы хотите создать 2 mocks для B
и C
и конкретный объект A
. Затем вы вводите эти 2 mocks в свой объект, и вы можете начать называть его методы.
Вероятно, это также причина, по которой вы получаете java.lang.AbstractMethodError
(этого недостаточно, чтобы подтвердить его). Если вы вызываете реальный метод на макет, тогда как этот метод является абстрактным (например, вы издеваетесь над интерфейсом или абстрактным классом), тогда эта ошибка возникает.
Ниже я опубликовал некоторый код и тест в качестве примера того, как вы можете вставлять mocks в конкретный объект.
В коде:
class A {
B b;
C c;
void doSomething() {
b.aMethod();
c.anotherMethod();
throw new IllegalArgumentException("something went wrong");
}
}
interface B {
void aMethod();
}
abstract class C {
void anotherMethod();
}
с тестом:
@RunWith(MockitoJUnitRunner.class)
class ATest {
@Mock B b;
@Mock C c;
// The inject mocks will insert both b and c into a by using reflection
@InjectMocks A a;
@Test(expected=IllegalArgumentException.class)
public void testSomething() {
a.doSomething();
}
}
getActivity
действительно вызывает метод onCreate
, поэтому он терпит неудачу с вашим запрограммированным исключением и выдает другой (RuntimeException
) сгенерированным в качестве основной причины.