Some thoughts on JUnit Test with Mockito Part II

So in the previous post we talked about some resources and concepts we should understand before writing JUnit tests with Mockito.

Well, based on my recent experience, they may not be enough, especially when our code has many dependencies or collaborators and we have to mock all of them to do the test. Things can become complicated very soon. If you find yourself in this situation, stop writing the test and refactor your code first, for example, by using the strategy pattern. In this way, you will likely have less collaborators to mock, but of course, you need to write tests for code delegated to other classes. There may be some extra work, but cleaner and easier.

Aside from this, my recent struggle also made me think about how to write unit test in general. I found another post about unit testing by Martin Fowler and read the first part of a book called “Effective Unit Testing”. There are some paragraphs that I find very helpful:

1) “We write tests assuming everything other than that unit under test is working correctly.” — Martin Fowler

Here “other than that unit under testing” usually means collaborators and we want to isolate them from the code under testing. By isolating them, we mean using test doubles to replace the real collaborators.

2) “A test should test just one thing and test it well while communicating its intent clearly.” We must ask ourselves:

What is the desired behavior for the code under testing? Think about how each step of your method should behave with certain inputs. The desired behavior of the dependencies is something we should configure the mocks to expect.

A general process could be:

Q: What do we want to test?

A: We want to test if method A is working properly.

Q: What do you mean by working properly?

A: By properly I mean that with a certain type of input INPUT, A should first call a dependency with INPUT and return a RESPONSE. Then A does some calculation by adding a number to some value stored in RESPONSE and return the sum. I expect that the sum is XXX.

Q: OK, so here we have a dependency. How do we deal with it?

A: We can isolate it by using a mock object to stub the RESPONSE when called with INPUT.

Q: Are there any requirements on the RESPONSE object?

A: Yes, since we are using some value in the RESPONSE, we should stub that value in the RESPONSE object. Otherwise, we might hit a null pointer exception situation.

Anyway, the key point is that we shouldn’t have too many dependencies for mocking in one unit test. Refactor the code first. Then work slowly through this process. Take your time.

Advertisements
Some thoughts on JUnit Test with Mockito Part II

Some thoughts on JUnit Test with Mockito

In the past a few days I’ve worked on writing unit tests for a service. It was a completely different experience. The unit tests I wrote before were very simple ones with several assertions and that’s it. However, since the service I’m writing involves calling other services, we have to mock their behaviors before testing our own part. Otherwise, if the dependent services are not working, or even not implemented, we won’t be able to do any test on our business logic at all.

It’s an easy idea to grasp, but it took me a while to understand the code. Before jumping into Mockito, there’s an article one should read: Mocks Aren’t Stubs by Martin Fowler. It explains classical and mockist testing in some details, a bit long but worth reading.

After reading that we should get an idea about mockist testing:

Set up -> Set Expectations -> Exercise -> Verification.

The second step is the part where we can tell the mocked dependent services how to behavior under certain conditions.

In the verification, we can still do the usual assertion but we also may need to verify that a dependent service is called as expected. Why do we need that? Say that you expect a method to return -1 with argument A. In an ideal successful case, we can just use assertEqual for testing. However, if the malfunction of a dependent service also causes the return value to be -1, then using assert statement alone will be insufficient. We need to make sure that a service is called and/or has the right return value.

After I got this idea, I moved on to Mockito framework, which is different from the ones mentioned in the article. But the idea is similar. There are two (actually three) articles I found online that helps you ease into using Mockito:

Occasionally we may have the need to mock static method. I had a really hard time with it when I was copying and pasting others’ test code. DON’T DO THAT! We are using PowerMock and I don’t know why I didn’t search for it early. Just RTFM, it’s actually very easy to use.

For my own reference:

To solve a problem, we need to locate the root cause first. We should set up some assumptions and verify them one by one.

Some thoughts on JUnit Test with Mockito