add a 'double' package that distinguishes Stubs, Spies and Mocks #1643
Replies: 2 comments 1 reply
-
When I talk in this area I use the language from Sandi Metz's book (poodr.com, chapter 9) which uses only "doubles" and "mocks".
While "testing for state" as Sandi recommends, I've never had the need for a "spy". This shouldn't be relevant to what I'm about to say, though. New packages or classes in this fork of testify are, in general, highly unlikely at this point. I think the current API is sufficient to do both and this is how I contstruct them by using variale naming and properly setting up the DoublesdatabaseDouble := &myMock{}
databaseDouble.Test(t) // Prevents panic on unexpected calls
databaseDouble.On("GetFullName", "mat").Return("Mat Ryer", nil)
// ...and so on This will return the information you tell it to. Changing your implementation is unlikely to need a change to the double. MocksmockDatabase := &myMock{}
mockDatabase.Test(t)
defer mockDatabase.AssertExpectations(t) // All calls were made or fail the test
mockDatabase.On("Delete", "mat").Return(nil).Once() // All calls should have an expected count
// ...and so on This will fail the test if the code under test didn't try to delete Mat. What about bothYou should consider whether your implementation is optimal before you do this, but if you can't or don't want to avoid your duck being a mock and double, you can do this: mockDatabase := &myMock{}
mockDatabase.Test(t)
defer mockDatabase.AssertExpectations(t)
mockDatabase.On("GetFullName", "mat").Return("Mat Ryer", nil).Maybe() // This call is a double
mockDatabase.On("Delete", "mat").Return(nil).Once() Here SpiesI don't use them, but I expect you could use |
Beta Was this translation helpful? Give feedback.
-
Thank you for your feedback. I'm a fan of the work of Sandi Metz. I particularly like this talk. I agree with you that it is possible to write stubs and mocks with the current version. However, I find some drawbacks:
I find some advantages to separate Stub and Mock notions:
Do you think it is worth distinguishing stubs and mocks? |
Beta Was this translation helpful? Give feedback.
-
Description
If we refer to a definition of test doubles, there is an interest in distinguishing stubs, spies and mocks.
Stubs provide canned answers to calls made during the test. For example, a stub needs to return a value in response of a query. If the code under test changes and no longer needs to make that
query, there is no reason that the test should break.
Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.
Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are
checked during verification to ensure they got all the calls they were expecting.
We can see the separation of concern between them as:
Proposed solution
There is a POC here
I try to explain the design choices in Architecture Decision Records.
All the ADR are negotiable, except perhaps the first one which is the purpose of the POC.
Opinion:
The POC introduces reflection (to know if a method have return parameters) and generics (to propose a constructor for Stubs, Spies and Mocks)
The purpose is to be as retro-compatible as possible to facilitate the migration.
It is opinionated. So I'll understand a reject. Even so, it was fun to code.
Use case
There is a comparison between the actual library and the proposition.
There is also examples of Stub, Spy and Mock
References
Can be referred to #483
Beta Was this translation helpful? Give feedback.
All reactions