2015-02-24 2 views
1

Я пытаюсь высмеять класс DateTimeFormatter. Я сделал следующее:Mock java.time.format.DateTimeFormatter class

@RunWith(PowerMockRunner.class) 
@PrepareForTest({DateTimeFormatter.class}) 
public class UnitTest { 

private DateTimeFormatter mockDateFormatter; 

private AwesomeClass awesomeClass; 

@Before 
public void setUp() { 
    mockDateFormatter = PowerMockito.mock(DateTimeFormatter.class); 
    awesomeClass = new AwesomeClass(mockDateFormatter); 
} 

@Test 
public void shouldToTestSomethingAwesome() { 
    // Other test code 
    PowerMockito.when(mockDateFormatter.format(any(LocalDate.class))) 
        .thenReturn("20150224"); 
    // Other test code 

} 

AwesomeClass использует его для форматирования LocalDateTime.now(ZoneId.of("UTC"));. Затем форматированная строка используется для генерации другой строки. Мне нужно убедиться, что строка правильно сгенерирована. Поэтому мне нужно вернуть согласованную дату либо из форматирования, либо изложить статический метод LocalDateTime.now (..)

Что я делаю неправильно?

+6

* Почему вы хотите высмеять 'DateTimeFormatter', из интереса? Почему бы вам не просто использовать настоящую? Я бы опасался чрезмерного насмешки - это может сделать тесты намного более хрупкими (и трудночитаемыми), чем просто использование реального кода или подделок с приблизительным таким же поведением. –

+1

Похоже, что модульное тестирование запускает a-mock для меня .... – duffymo

+0

Класс, в который я передаю форматтер, использует его для форматирования 'LocalDateTime.now (ZoneId.of (« UTC »));'. Затем форматированная строка используется для генерации другой строки. Мне нужно убедиться, что строка правильно сгенерирована. Поэтому мне нужно вернуть согласованную дату либо из форматирования, либо издеваться над 'LocalDateTime.now (..)' static method –

ответ

4

Альтернативой насмешливый LocalDateTime.now() это вводить часы в классе и изменить свой (или добавить другой) конструктор, как это:

AwesomeClass(DateTimeFormatter fmt, Clock clock) { 
    //instead of LocalDateTime now = LocalDateTime.now(): 
    LocalDateTime now = LocalDateTime.now(clock); 
} 

Тогда в тесте:

new AwesomeClass(formatter, Clock.fixed(the time you want here)); 
+1

Если это не ясно, вполне разумно добавить второй конструктор (закрытый для пакета) для целей вашего теста. Например, ваш существующий конструктор может быть изменен для вызова private-пакета с аргументом 'Clock.systemUTC()', например. –

8

О рынке mockito wiki: Don't mock types you don't own !

Это не сложно. ne, но пересечение этой линии может иметь последствия! (это, скорее всего, будет.)

  1. Представьте код, издевающийся над третьей стороной lib. После определенного обновления третьей библиотеки логика может немного измениться, но набор тестов будет выполняться просто отлично, потому что это насмехается. Поэтому позже, думая, что все хорошо, строительная стена в конечном счете зеленая, программное обеспечение развернуто и ... Boom
  2. Это может быть признак того, что текущий дизайн не отделился от этой третьей партийной библиотеки.
  3. Еще одна проблема заключается в том, что сторонняя библиотека может быть сложной и требует много макетов даже для правильной работы. Это приводит к чрезмерно указанным испытаниям и сложным светильникам, что само по себе компрометирует компактный и читаемый цель . Или к тестам, которые недостаточно покрывают код, из-за сложности издеваться над внешней системой.

Вместо этого наиболее распространенным способом является создание оберток вокруг внешней библиотеки lib/system, хотя следует помнить о риске утечки абстракции, где слишком много API, концепций или исключений низкого уровня выходит за границы обертки. Чтобы проверить интеграцию с сторонней библиотекой, запишите тесты интеграции и сделайте их как можно более компактными и читаемыми.

Mock типа, что вы не имеете контроля можно считать (насмешливый) антипаттерн. В то время как DataTimeFormatter в значительной степени стандарт, не следует учитывать, что в предстоящих выпусках JDK не будет изменений в поведении (это уже было много раз в другой части API, просто посмотрите заметки о выпуске JDK).

Я хочу сказать, что если код нуждается в том, чтобы издеваться над типом, который у меня нет, дизайн должен изменить asap, так что я, мои коллеги или будущие сторонники этого кода не попадут в эти ловушки.

Также wiki ссылается на другие записи в блогах, описывая проблемы, которые у них были, когда они пытались имитировать тип, которым они не обладали контролем.

+0

Это 2018 год, и ваша связь мертва. Что действительно означает этот ответ? Кто знает! –

+0

@ Duncan no it is not – Brice

+0

Либо напишите свой ответ с некоторой информацией с этой страницы, либо измените это на комментарий по вопросу, где те же правила качества не применяются. Ссылки ** do ** break, поэтому в один прекрасный день ваш ответ может просто прочитать «* Не издевайтесь над типами, которыми вы не владеете!», Что не так полезно. –

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