是一个模拟的MongoRepository保存对象吗?

时间:2018-02-21 08:29:57

标签: 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时,它会发生一些我不期望的事情。 counterRepository.findById()返回一个Counter对象,其中&#39; seq&#39;场增加了。为什么? 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"));
    }
}

它打印&#34; 10 11 12&#34;。为什么不打印&#39; 10 10 10&#39;?

2 个答案:

答案 0 :(得分:0)

问题是这些行

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

你应该做的是这个

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

在getSeqAndIncrease方法中,您不返回已保存对象的序列 通过执行此操作,您将使保存的模拟语句无效。因为您没有使用mock返回的值。

答案 1 :(得分:0)

tl; dr - mock中返回的对象仅在mockito中初始化一次。所以我基本上每次都得到相同的引用,因为它是一个引用而不是一个新对象,所以值会更新。

完整答案:设置时

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

,每次返回一个新对象似乎都很直观,但返回对象在测试开始时只初始化一次,并在所有后续调用时返回。

然后,在我的代码中我做

counter.increaseSeq(); 

增加了&#39; seq&#39;找到的对象(此对象来自Mockito)。然后在下一次调用时,Mockito返回第一个初始化的对象,该对象在此期间更新; Mockito并没有像它看起来那样返回一个新对象。