2013-08-16 2 views
3

Я пытаюсь выполнить модульный тест класса, который нуждается в зависимости. Создание класса зависимости напрямую невозможно, поскольку конструктор зависимости имеет логику, которая нуждается в объектах, доступных только во время выполнения.Избегайте исключения javax/ejb/EJBLocalObject, когда насмехается с PowerMock

Однако, когда я пытаюсь высмеять класс зависимостей, я получаю исключение «java.lang.NoClassDefFoundError: javax/ejb/EJBLocalObject». Как я могу обойти это? Единственное решение, о котором я могу сейчас думать, это изменить ClassToTest на использование интерфейса вместо фактического конкретного класса Dependency.

Некоторые код, чтобы показать, как я в настоящее время пытается издеваться зависимость:

package mockTest; 

import org.junit.Test; 
import org.powermock.api.mockito.PowerMockito; 

public class MockTest { 

    @Test 
    public void performTest() { 
     // Mock the dependency and create the class to test 
     Dependency dependency = PowerMockito.mock(Dependency.class); 
     ClassToTest classToTest = new ClassToTest(dependency); 

     // Invoke a method in classToTest, assert.. 
    } 
} 

Дальнейшее уточнение:

Вопрос: Является ли Зависимая класс осущ интерфейса?

ClassToTest (зависимый класс) является конкретным классом и не имеет интерфейсов, хотя он легко мог - я контролирую источник. Класс Dependency - это конкретный класс, который не реализует интерфейсы, и я не контролирую источник.

Вопрос: Вы только проходите в объекте «зависимость», потому что он создается в обычном конструкторе, поэтому, предоставляя один, вы пытаетесь приручить рабочий Mock вместо созданного?

Да. ClassToTest использует методы зависимости, которые вызывают зависимость, например, вызовите JDBC. Я хочу иметь возможность либо перейти в фактическую зависимость (от кода реализации), либо сделать mock (из тестового кода).

В: Является ли зависимость статической?

Нет, зависимость или методы зависимостей не являются статическими.

+0

1. Является ли Зависимая класс интерфейс интерфейса? 2. Переходите ли вы только к объекту «зависимость», потому что он создается в обычном конструкторе, поэтому, предоставляя один, вы пытаетесь и приватируете рабочий Mock вместо созданного? 3. Является ли зависимость статической? – Walls

ответ

1

После дальнейших исследований эта проблема, похоже, связана с тем, как Maven используется для создания проекта, над которым я работаю.

java.lang.NoClassDefFoundError выбрано потому, что артефакт Maven, содержащий javax.ejb.EJBLocalObject, имеет область Maven 'provided'. Это заставляет использовать объект Dependency для работы в коде реализации во время выполнения. Однако, когда тестовый код пытается издеваться над зависимостью, артефакт Maven недоступен, и вызывается NoClassDefFoundError.

Быстрый способ решить эту проблему можно было бы добавить то, что содержит javax.ejb.EJBLocalObject как зависимость Maven с тестовой рамкой к POM, например:

<!--Provides javax.ejb.EJBLocalObject to tests, enabling mocking of Dependency--> 
<dependency> 
    <groupId>jboss</groupId> 
    <artifactId>jboss-j2ee</artifactId> 
    <version>3.2.1</version> 
    <scope>test</scope> 
</dependency> 
1

Наличие конструктора классов, для которого требуется тонна зависимых объектов (singleton static во время выполнения и т. Д.), Всегда является болью при создании макетных тестов. Лучший способ, который я могу придумать, - использовать некоторую комбинацию вызова Powermockito.whenNew() и вызова Mockito.any(Class.class). Таким образом, когда вы вызываете свой конструктор, вы можете подключать нужные объекты. Если вы следуете аналогичному шаблону одноэлементности на ваших зависимых объектах, вы можете издеваться над этими классами getInstance(), чтобы вернуть вам копию макета, который вы создаете в тестах.

Пример:

Dependency dependMock = PowerMockito.mock(Dependency.class); 
PowerMockito.whenNew(Dependency.class).withNoArguments().thenReturn(dependMock); 

ИЛИ, если Dependency нуждается арг прошли в для 2-го зависимости уровня:

Dependency dependMock = PowerMockito.mock(Dependency.class); 
PowerMockito.whenNew(Dependency.class) 
    .withArguments(Mockito.any(LevelTwoDependency.class)).thenReturn(dependMock); 

Обратите внимание, что при использовании whenNew вам нужно иметь крюк для класс, который вы тестируете, так что код запускается. Это можно сделать, добавив некоторые тестовые аннотации для тестового класса.

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ClassYouAreTesting.class}) 
public class ClassTest{ 
    // code  
} 

Это позволяет вам полностью контролировать объекты зависимостей 2-го уровня с помощью Mocks. Удалив их из логики (предоставляя функциональность Mocked), вы попадаете в суть ваших тестов, что заканчивает тестирование чистой функциональности вашего класса.Удаляя любое нечетное поведение из этих зависимых классов, вы устраняете риск наличия ошибок в этом коде, что в конечном итоге приведет к нарушению и даст ложные результаты теста для любого класса с использованием этих классов зависимостей.

Путем соединения этих Mocks вы можете в основном издеваться над основным зависимым классом и всеми его классами зависимостей, используя другие mocks. Он может немного запутаться в зависимости от того, как работают constrcutors, и вы настраиваете частные переменные для этих объектов.

+0

Исключение java.lang.NoClassDefFoundError: javax/ejb/EJBLocalObject происходит уже при создании зависимости; поэтому, когда я это делаю "Dependency dependMock = PowerMockito.mock (Dependency.class);" в тестовом коде генерируется исключение. Таким образом, хотя эти пункты полезны, они, к сожалению, не разрешают проблему. –

 Смежные вопросы

  • Нет связанных вопросов^_^