Is there a way to mock only part of an object in Dart with Mockito?
Asked Answered
K

2

11

I am currently trying to develop test-driven with Flutter and Dart. I have an object that has two methods of which the first one does an http call and the second one calls the first method. In order to test the first function I mock the dependencies of the that function (namely the http call).

Now I want to test the second method, but I was not able to find a way to mock only the first function while keeping the rest of the object intact. As a result I can only mock the dependencies of the first method again which results in the entire function being executed all over. This goes against the whole purpose of unit testing.

It seems like there is only an all or nothing approach when it comes to mocking objects. I wonder how one is to go about a case where some object is reliant on methods on the same object. Using Fake and Mock does not allow me to call the original method. spy is deprecated and assigning a mock function to one of the functions does not work since Dart does not allow me to reassign a method.

Kickstand answered 27/5, 2020 at 15:42 Comment(3)
1. You could make your Mock object delegate to a real object for some operations (although doing so is discouraged). 2. In your particular case, perhaps you could mock HttpClient instead with HttpOverrides?Subtropics
Thank you for your suggestions. I also thought about option one, but since I call the first method as this.firstMethod() it is bound to the object and automatically called when the first one is called. Replacing the call would only work with DI passing a new this. Or am I missing something? While HttpOverrides are useful in general, I don't see how it can help me mitigate executing the code from the first method again. I would like to stick to one test for one function.Kickstand
@Subtropics thank you. Your link led me to a decent way of going about the problem. See below.Kickstand
K
2

I found a way to solve my problem. According to this link mentioned in the comments "[t]esting with real objects is preferred over testing with mocks". In my case I just subclassed the main object I was testing and replaced the (second-)method that I was not testing. This seems to do the trick.

Kickstand answered 28/5, 2020 at 8:4 Comment(0)
S
1

Perhaps this doesn't apply to you, but it applied to me and maybe to some of you reading this. Perhaps your code isn't decoupled enough, and you might need to follow something like clean architecture to decouple it.

The short answer would be: Split it into two different classes. This way, one of the classes will receive the other one as a parameter, and you can mock one of them and use the other one as a normal object.

Long answer: Take a look at clean architecture or any other architecture that facilitates testing by abstracting classes and using interfaces.

Sclerenchyma answered 24/1 at 2:13 Comment(1)
While this is not a direct answer, generally you are right. Nowadays I would solve this differently. "Dependency Injection" and "Refactoring" would be the correct answer. If you cannot test something easily, you are doing it wrong.Kickstand

© 2022 - 2024 — McMap. All rights reserved.