Rethink unit test in scala

A summary of my thoughts

scalamock

scalamock is a pure scala library to mock objects. Also it’s the one I used most of the time in scala. There are two mocking styles in scalamock. One is expectation-first style(mock) and another is record-then-verify(stub). Expectation-first style sets the expectation first and then call actual function to verify the expectation meet. And record-then-verify is more like given-when-then style. We setup the instance and call the method and finally verify the behavior or state.

The first style is behavior verification and the second one is a mixing of behavior and state verification. And I like state verification the most. Coz I don’t want to write something like which method is called with which parameter how many times. I don’t care about the interactions, I just care about the final result or the final state of the environment(subject under test and its collaborators) after function invocation.

Notice that private method and protected method cannot be stub in scalamock. Especially when you try to stub java class with protected methods, there will be exceptions like method not found error. And there’s no partial mock in scalamock. That means it’s not possible to call the real method of stubbing class like mockito spy does.

mockito

You should know mockito if you come from java. It’s a famous mocking library in java. If u want to use it in scala, I suggest u to add a dependency of mockito-scala. So you could write your code in scala style, such as no more mock(classOf[SUT]), you can do mock[SUT] directly. It provides scala style syntax porting to original java library.

I suggest u to use mockito if u want the feature of spy or the feature of stubbing protected method. And if your class interacts a lot with java codes, you’d better use mockito. It’s very likely the class could be an abstract class with protected methods. Finally, if you are familiar with mockito, there’s no reason not to use it.

behavior verification vs state verification

I prefer state verification. I don’t want to care about the interactions between the SUT(system under test) and its collaborators.

make code testable

The situation I meet most is that the code is not testable. The coders use third party dependencies directly in their code. There’s no way to inject the dependencies. So please always remember interface-oriented programming. Always leave a way for a mock instance to be injected, such as via constructors, setters or fields.

Ref

https://martinfowler.com/articles/mocksArentStubs.html

I suggest everyone to read this article by Martin Fowler if you have doubt about how to write a unit test. It’s never out of date.