Может ли кто-нибудь помочь мне издеваться над статическим методом, который возвращает объект, и этот статический метод присутствует в конечном классе

Мне нужна помощь для того, что ниже,

Мне нужно написать Junit, используя PowerMock/Mockito для метода, который вызывает статический метод конечного класса, присутствующего во внешнем банке.

Метод, для которого мне нужно написать тест JUnit:

public class SomeClass {
    private PrivateKey privateKeyFromPkcs8(String privateKeyPem) throws IOException {
        Reader reader = new StringReader(privateKeyPem);
        Section section = PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY");
        if (section == null) {
            throw new IOException("Invalid PKCS8 data.");
        }
        byte[] bytes = section.getBase64DecodedBytes();
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
        try {
            KeyFactory keyFactory = SecurityUtils.getRsaKeyFactory();
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        } catch (NoSuchAlgorithmException exception) {
        } catch (InvalidKeySpecException exception) {
        }
        throw new IOException("Unexpected exception reading PKCS data");
    }
}   

В приведенном выше коде PemReader — конечный класс, а readFirstSectionAndClose(reader, "PRIVATE KEY") — статический метод в PemReader.

Я попытался написать тест, показанный ниже, но Section object(section) отображается как нуль во время отладки. Возможно, вместо макета вызывается реальный код (PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY")).

@RunWith(PowerMockRunner.class)
@PrepareForTest({SomeClass.class,PemReader.class})
public class SomeClassTest {
    @InjectMocks
    SomeClass mockSomeClass;

    @Mock
    private Reader mockReader;

    @Mock
    private Section mockSection;

    @Test
    public void testPrivateKeyFromPkcs8() throws Exception {   
        PowerMockito.mockStatic(PemReader.class);
        Mockito.when(PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY")).thenReturn(mockSection);

        assertNotNull(mockSomeClass.privateKeyFromPkcs8(dummyPrivateKey));
    } 

 }

Пожалуйста, помогите мне написать Junit, используя powermockito/mockito.


person gopi naik    schedule 01.10.2017    source источник


Ответы (1)


Вам нужно подготовить окончательный статический класс.

Вот пример использования аннотаций PowerMock для JUnit:

@RunWith(PowerMockRunner.class)
@PrepareForTest({PemReader.class})
public class PemReaderTest {

    @Mock
    private Reader mockReader;

    @Mock
    private Section mockSection;

    @Test
    public void testMockingStatic() {
        PowerMockito.mockStatic(PemReader.class);

        Mockito.when(PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY")).thenReturn(mockSection);

        Assert.assertEquals(mockSection, PemReader.readFirstSectionAndClose(mockReader, "PRIVATE KEY"));
    }
}

Для полноты вот определение PemReader:

public final class PemReader {

    public static Section readFirstSectionAndClose(Reader reader, String key) {
        return null;
    }
}

Приведенный выше тест проходит со следующими версиями:

  • Юнит: 4.12
  • Мокито: 2.7.19
  • PowerMock: 1.7.0

Обновление 1: на основе обновленного вопроса. Ваш тестовый пример пройдет (или, по крайней мере, вызов PemReader.readFirstSectionAndClose что-то вернет), если вы просто сделаете это изменение:

Mockito.when(PemReader.readFirstSectionAndClose(
    Mockito.any(Reader.class), 
    Mockito.eq("PRIVATE KEY"))
).thenReturn(mockSection);

Версия этой инструкции в вашем текущем тестовом примере основана на сопоставлении равенства между StringReader, которое ваш код передает в readFirstSectionAndClose, и имитируемым Reader, который предоставляет ваш тестовый пример. Они не «равны», поэтому ожидания имитированного вызова не оправдываются, и ваш mockSection не возвращается.

Несколько не связанных между собой заметок:

  • Нет необходимости включать SomeClass.class в @PrepareForTest, вам нужно только включить в эту аннотацию классы, которые вы хотите имитировать, поскольку SomeClass - это класс, который вы пытаетесь протестировать, для этого класса не требуется насмешка.
  • Использование @InjectMocks для экземпляра SomeClass немного странно, поскольку SomeClass не имеет (предоставленных mockito) макетов для внедрения в него :) вы можете заменить это объявление на SomeClass someClass = new SomeClass();
  • В предоставленном вами коде SomeClass.privateKeyFromPkcs8 имеет частную область, поэтому его нельзя протестировать (или каким-либо образом вызвать) из SomeClassTest.
person glytching    schedule 01.10.2017
comment
Позвольте мне объяснить реальную проблему. у меня есть класс, скажем, Class x , в котором у меня есть метод private PrivateKey privateKeyFromPkcs8 (String privateKeyPem) ниже приведен код метода - person gopi naik; 02.10.2017
comment
private PrivateKey privateKeyFromPkcs8 (String privateKeyPem) выдает IOException { Reader reader = new StringReader (privateKeyPem); Раздел section = PemReader.readFirstSectionAndClose (читатель, ЗАКРЫТЫЙ КЛЮЧ); if (section == null) { throw new IOException (Недопустимые данные PKCS8.); } byte[] bytes = section.getBase64DecodedBytes(); PKCS8EncodedKeySpec keySpec = новый PKCS8EncodedKeySpec (байты); попробуйте { KeyFactory keyFactory = SecurityUtils.getRsaKeyFactory(); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); вернуть приватный ключ; } поймать (исключение NoSuchAlgorithmException) { - person gopi naik; 02.10.2017
comment
} catch (исключение InvalidKeySpecException) { } throw new IOException (неожиданное исключение при чтении данных PKCS); } - person gopi naik; 02.10.2017
comment
И я хочу протестировать этот метод с помощью Junit. Помогите пожалуйста как написать. - person gopi naik; 02.10.2017
comment
@gopinaik звучит так, как будто для этого может потребоваться отдельный вопрос или, по крайней мере, обновить этот вопрос, включив в него эти детали и заявление о том, что вы хотите, чтобы этот тест делал. Очень сложно понять код, размещенный в комментариях, особенно когда этот код разбит на два комментария :) - person glytching; 02.10.2017
comment
Привет, глюк, я обновил свой вопрос. Не могли бы вы помочь мне сейчас? - person gopi naik; 02.10.2017
comment
@gopinaik Я взял ваш обновленный вопрос, воспроизвел проблему «нулевого ответа» локально, а затем исправил ее, обновленный ответ включает исправление. - person glytching; 02.10.2017
comment
теперь это работает. Объект раздела теперь не нулевой. Спасибо :) - person gopi naik; 03.10.2017