/ / Чи фіктивний MongoRepository зберігає об'єкти? - spring, spring-mvc, spring-boot, spring-data, spring-boot-test

Чи є знущальним збереженням об'єктів MongoRepository? - spring, spring-mvc, spring-boot, spring-data, spring-boot-test

Я використовую SpringBoot 1.5.9 і намагаюся зробити інтеграційне тестування. Дивно, що метод MongoRepository.save () оновлює об'єкт при виклику на макет MongoRepository.

У мене є лічильник класу

public class Counter {
public String id;
public int seq;

public void increaseSeq() {
this.seq += 1;
}
}

І його сховище

public interface CounterRepository extends MongoRepository<Counter, String>{
Counter findById(String id);
List<Counter> findAll();
}

І його служба

@Service
public class CounterService {
@Autowired private CounterRepository counterRepository;


public Counter findCounter(String id) {
return counterRepository.findById(id);
}

public int getSeqAndIncrease(String id) {
Counter counter = findCounter(id);
if (counter == null) {
return -1;
}

counter.increaseSeq();

counterRepository.save(counter);

return counter.getSeq();
}
}

Тепер, коли я роблю системну інтеграцію і намагаюся знущатисяcounterRepository, трапляється те, чого я не очікую. CounReRepository.findById () повертає об'єкт Counter, де поле "seq" збільшено. Чому? Чи впливає counterRepository.save () якимось чином на результат (counterRepository знущаються, отже, я вважаю, що save () не повинно мати жодного ефекту)?

@RunWith(SpringRunner.class)
@SpringBootTest
public class FlowServiceTest {
@MockBean private CounterRepository counterRepository;
@Autowired private CounterService counterService;

@Before
public void setUp() {
Mockito.when(counterRepository.save(any(Counter.class))).then(arg -> arg.getArgumentAt(0, Counter.class));
Mockito.when(counterRepository.findById("flow")).thenReturn(new Counter("flow", 10));
}

@Test
public void testSavingInDatabase() {
System.out.println(counterRepository.findById("flow"));

counterService.getSeqAndIncreaseSafe("flow");
System.out.println(counterRepository.findById("flow"));

counterService.getSeqAndIncreaseSafe("flow");
System.out.println(counterRepository.findById("flow"));
}
}

Друкується "10 11 12". Чому не друкується «10 10 10»?

Відповіді:

0 для відповіді № 1

Проблема в цих рядках

counterRepository.save(counter);
return counter.getSeq();

Що ви повинні робити, це це

Counter saveCounter = counterRepository.save(counter);
return savedCounter.getSeq();

У методі getSeqAndIncrease ви не повертаєте послідовність збереженого об'єкта.
Роблячи це, ви робите свою фіктивну заяву для зберегти марно. Оскільки ви не використовуєте значення, повернене з макета.


0 для відповіді № 2

tl; dr - Повернутий об'єкт з mock ініціалізується лише один раз у mockito. Отже, я в основному отримував одне і те ж посилання кожного разу, і оскільки це посилання не є новим об’єктом, значення оновлюються.

Повна відповідь: При встановленні

Mockito.when(counterRepository.findById("flow")).thenReturn(new Counter("flow", 10));

, може здатися інтуїтивно зрозумілим повертати новий об’єкт кожного разу, але об’єкт повернення ініціалізується лише один раз, коли запускається тест, і буде повернутий при всіх наступних викликах.

Потім у своєму коді я це роблю

counter.increaseSeq();

що збільшує "seq" знайденого об'єкта (thisоб'єкт походить від Mockito). Потім при наступному виклику Mockito повертає перший ініціалізований об’єкт, який тим часом був оновлений; Mockito не повертає новий об'єкт, як може здатися.