#java #mockito
#java #mockito
Вопрос:
Были похожие вопросы, но ни один из них не может решить мою текущую проблему
Допустим, у меня есть довольно простой класс:
public class ClassA {
private final Object someVariable;
public classA(Object obj) {
this.someVariable = obj
}
public void Object someMethod(Object obj) throws SomeException {
//does stuff
}
}
Теперь я создаю экземпляр этого класса в классе diff
public class ClassB {
private final Object anotherVariable;
public void Object anotherMethod() throws SomeException {
try {
ClassA objectA = new ClassA(anotherVariable)
objectA.someMethod()
} catch {
// does stuff
}
}
}
Конечная цель — протестировать блок catch, создав исключения таким образом
@Mock
ClassA myObject = new ClassA(obj)
...
@Test(expected = SomeException.class)
public void myTest()throws Exception {
doThrow(new SomeException()).when(myObject).someMethod(any());
}
По какой-то причине исключения просто никогда не выбрасываются. Я также пытался any()
заменить как на допустимые, так и на недопустимые объекты, и это все равно не работает.
Правка1:
Во время поиска решения это по какой-то причине проходит тест:
@Test(expected = SomeException.class)
public voif Test() throws Exception {
doThrow(new someException()).when(myObject).someMethod(any());
when(myObject.someMethod(any())).thenThrow(new someException());
}
Любое объяснение того, почему это работает? Это плохая практика или что-то в этом роде?
Комментарии:
1. Попробуйте это
doThrow(SomeException.class)
Ответ №1:
Я считаю, что причина в том, что вы никогда не вызываете метод:
@Test(expected = SomeException.class)
public void myTest(0 throws Exception {
// here you stub the method
doThrow(new SomeException()).when(myObject).someMethod(any());
// also it should probably be like this:
// doThrow(new SomeException()).when(myObject).someMethod();
// because the method in ClassA does not have any params
// you need it to be called somewhere
// you can do that explicitly
myObject.someMethod(/*perhaps some param here*/);
// or you can call some other method which calls this one
// on the mock - then you should get an exception as well
}
Кроме того, в ClassB есть небольшая проблема:
public void Object anotherMethod() throws SomeException {
try {
// you instantiate obj of type ClassA here
// which means you cannot mock it if you need
// to test anotherMethod()
ClassA objectA = new ClassA(anotherVariable)
objectA.someMethod()
} catch {
// does stuff
}
}
Если вы хотите протестировать ClassB.anotherMethod()
, вам нужно избавиться от этой сверхтяжелой связи:
ClassA objectA = new ClassA(anotherVariable)
Рассмотрите такой подход:
public class ClassB {
private final ClassA objectA;
public ClassB(ClassA obj) {
// now you can provide any instance of ClassA instead
// of having it created in try-block later
// so when you need ClassB in real code, you can create
// some real instance of ClassA and pass to this conctructor
// and for test you can pass mock
this.objectA = obj;
}
public void Object anotherMethod() throws SomeException {
try {
objectA.someMethod()
} catch {
// does stuff
}
}
}
Что это нам дает:
@Mock
ClassA myObject = new ClassA(obj)
...
@Test(expected = SomeException.class)
public void myTest()throws Exception {
// stub someMethod on object of ClassA
doThrow(new SomeException()).when(myObject).someMethod();
ClassB objB = new ClassB(myObject);
// now you can test it, and inside anotherMethod()
// there will be a call to someMethod() on a mock
// so you will get an exception
objB.anotherMethod();
}
Комментарии:
1. Это сработало! Моя следующая проблема / вопросы: конечная цель — в основном протестировать блок catch в ClassB, где вызывается someMethod, с помощью doThrow() Я попытался вызвать anotherMethod, который, в свою очередь, вызывает someMethod, но безуспешно
2. @ElizabethSallow Я обновил свой ответ более подробной информацией о том, как вы можете протестировать свой ClassB. Надеюсь, они имеют какой-то смысл 🙂
3. О, теперь это имеет больше смысла, спасибо! Поддержано и принято в качестве ответа.
Ответ №2:
Я предполагаю, что, поскольку вы издеваетесь над классом A ниже строки
@Mock
ClassA myObject = new ClassA(obj) //u r creating new instance
сделать
@Mock
ClassA myObject; //assuming u r using initMock or @InjectMocks
или
ClassA myObject = Mockito.mock(ClassA.class);
затем имитируйте поведение, как вы имитируете вызов метода
when(myObject.someMethod(any()))
.thenThrow(new SomeException());
Комментарии:
1. К сожалению, не сработало, хотя могу ли я спросить, в чем разница между этим и doThrow (new
SomeException()).when(myObject).someMethod(any())
;2. один предназначен для макета, другой — для объекта-заглушки