eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.22k stars 170 forks source link

Cannot verify 0 times invocations using RepeatedSequence #308

Open jussi-muhonen-nexstim opened 1 year ago

jussi-muhonen-nexstim commented 1 year ago

When running data driven tests it sometimes required to verify 0 invocations in chain of sequences. This is currently impossible as 0 is not allowed in RepeatedSequence operator*(const Sequence&, int times). Relaxing the requirement to not allowing negative numbers lets the tests pass but then the 0 is not used but only ignored. This requires to require Exactly(0) calls to mocked function.

It would be great to allow 0 and then require 0 invocations as well in RepeatedSequence.

ps. My humblest thanks to everyone working on this project, it's a lifesaver (at least time saver!)

FranckRJ commented 1 year ago

Verify(Method(mock,foo) * n); means "foo is called n times consecutively at least once". If n is 0 then I'm not sure if it should really verify that foo is never called. But maybe Verify(Method(mock,foo) * 0).Once(); should check that.

Could you provide an example of what you want to check exactly (just to be sure I understand correctly) ?

Anyway, I think you're right that a feature like that could be useful, I'll think about it.

jussi-muhonen-nexstim commented 1 year ago

@FranckRJ thank you for your response.

The feature would indeed be very useful when using data driven tests. Lets think of a function that would initialize, read data from and close a resource. Calls to resource would have always one init, 1 to n read data and 0 to 1 close. Each of the calls may fail and the idea would be to test that we verify the call order and how many calls to each resource funtions.

The data would be using params {initCalls, readCalls, closeCalls}: {1, 0, 0} when initialization fails {1, 1, 0} when first read fails {1, n, 0} when nth read fails {1, n, 1} when all reads succeed

It would be awesome just to have single expression: Verify(Method(mock, init) * initCalls, Method(mock, read) * readCalls, Method(mock, close) * closeCalls).Once()

We have made the change to allow 0 as a value and the drawback as you mentioned is that we have to verify calls using redundant expressions: Verify(Method(mock, init)).Exactly(initCalls) Verify(Method(mock, read)).Exactly(readCalls) Verify(Method(mock, close)).Exactly(closeCalls)

This is because RepeatedSequence with + 0 times means any number of invocations.

FranckRJ commented 1 year ago

Verify(Method(mock, init) * initCalls, Method(mock, read) * readCalls, Method(mock, close) * closeCalls).Once()

This will never work, because the comma operator is a "weak" ordering, it means "there's initCalls consecutive calls to init somewhere before the readCalls consecutive calls to read". To verify a "strong" ordering (first sequence is immediately followed by the second sequence) you need to use the + operator.

You should also always call VerifyNoOtherInvocations to be sure there's no other calls before or after the sequence.

jussi-muhonen-nexstim commented 1 year ago

I got the chance to test the operator+ and VerifyNoOtherInvocations and the combination seems to work perfectly with * 0 invocations.