2016-07-20 4 views
1

У меня очень сложный класс для написания тестового примера Junit. Я решил использовать PowerMockito, так как мой класс, для которого должен быть запущен тест, имеет инициализацию конструктора.Ошибка PowerMockito с использованием InjectMocks

Мой главный класс, как это:

public class MainClass extends BaseClass{ 

MainClass(SomeClass class){ 
    super(class); 
} 

public void methodToBeTested(){ 
some code here 
} 

..few other methods which I am not going to test. 
} 

Теперь я тестовый пример написан так:

@RunWith(PowerMockRunner.class) 
public class TestClass{ 

@Mock 
OtherClassUsedInMainClass mock1; 

@Mock 
OtherClassUsedInMainClass mock2; 

@InjectMocks 
MainClass mainClass; 

@Before 
public void setUp() throws Exception{ 
    MockitoAnnotations.initMocks(this); 
    PowerMockito.whenNew(MainClass.class).withArguments(Mockito.any(SomeClass.class)) 
      .thenReturn(mainClass);) 
} 

@Test 
public void testMethodtobeTested(){ 
    ...I am using the other objects to mock data and test if this method works fine 

    mainClass.methodtobeTested(); 
    \\This method will increment a value. I am just asserting if that value is right. 
    Assert.assertEquals(mainClass.checkCount(),RequiredCount) 

} 

} 

Я получаю исключение в нулевой указатель при выполнении TestCase поскольку оно пытается инициализировать mainclass . Это не издевается. Я знаю, что делаю что-то неправильно. Но я просто не знаю, что это.

Ошибка:

org.mockito.exceptions.base.MockitoException: 
Cannot instantiate @InjectMocks field named 'mainClass' of type 'class com.main.MainClass'. 
You haven't provided the instance at field declaration so I tried to construct the instance. 
However the constructor or the initialization block threw an exception : null 

Caused by: java.lang.NullPointerException 
This null pointer exception is thrown from a the constructor of the BaseClass when it tries to initialize another class. 
+0

Показать конструктор BaseClass. Там вы получите сообщение об ошибке – Jens

+0

Почему вы стучите по MainClass? Разве это не тот класс, который вы тестируете? –

+0

@Jens Конструктор базового класса принимает someClass, переданный из mainClass в качестве аргумента. Он также использует этот someClass и использует его для инициализации нескольких других классов, которые также имеют конструктор, который использует someClass. – v1shnu

ответ

0

Цитирование this answer, который со ссылкой на @InjectMocks documentation:

Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. Note: If arguments can not be found, then null is passed.

Таким образом, по-видимому, объявить поле типа SomeClass и аннотировать его @Mock.

1

This question объясняет разницу между @Mock и @InjectMocks:

@Mock создает макет. @InjectMocks создает экземпляр класса и вставляет в него этот файл, который создается с помощью аннотаций @Mock (или @Spy).

MainClass конструктор ожидает параметр SomeClass, но для этого нет никакого макета.

Ваш код должен быть что-то вроде:

@RunWith(PowerMockRunner.class) 
public class TestClass{ 

    @Mock(answer = Answers.RETURNS_DEEP_STUBS) 
    SomeClass mock1; 

    @InjectMocks 
    MainClass mainClass; 

    @Before 
    public void setUp() throws Exception{ 
    ... 
+0

Я сделал это. Но все же код переходит в BaseClass. Я снова получаю нулевой указатель из BaseClass, когда он пытается инициализировать. – v1shnu

+0

@ViChU Я ожидаю, что это совсем другое, и это как-то связано с тем, как использует базовый класс. возможно, что-то делает с объектом возврата из метода из SomeClass. попробуйте использовать @Mock (answer = Answers.RETURNS_DEEP_STUBS) – user1121883

+0

Я пробовал это. Он по-прежнему выбрасывает null из BaseClass.Когда MainClass const вызывает super (someClass), он вызывает BaseClass const с someClass. Внутри конструктора создается несколько объектов. Некоторый доступ к объекту someClass, в то время как другие используют someClass в своем конструкторе. – v1shnu

0

Если вы не можете показать нам фактический код, очень трудно догадаться, что именно происходит. Но похоже, что ваш макет SomeClass нуждается в некотором затухающем поведении, чтобы удовлетворить конструктору BaseClass.

Например:

// the instance of MainClass you run your tests against 
private MainClass instance; 

@Mock 
private SomeClass someClass; 
@Mock 
private SomethingElse somethingElse; 

@Before 
public void setUp() { 
    when(someClass.doSomething()).thenReturn(somethingElse); 
    instance = new MainClass(someClass); 
} 

@Test 
public void test() { 
    // SETUP 
    when(somethingElse.doWeirdStuff()).thenThrow(new WeirdException()); 

    // CALL 
    instance.performTapDance(); 

    // VERIFY 
    assertTrue(instance.isWeird()); 
} 
Смежные вопросы