3

TL;DR There are no methods in VIPER which are returning any value so how to test them?

Reasoning:

In VIPER, each layer is communicating with other layer by holding an abstract reference to it (Protocols/Interfaces).

For e.g, View has reference of a Presenter. If view calls presenter.getSomething() presenter will not return a value right away. Instead, presenter will have a reference of view, and after completing its operations presenter will call view.setSomething(something).

This flow is consistent across all the flows between the layers. And to paraphrase it, classes that implement these protocols/interfaces, will only expose the methods they implement from protocols and interfaces as public. While writing tests you can only access these public methods, and, all of these methods return null.

The argument that you can return a value is not valid enough in real life cases where operations that are performed after a call must be asynchronous, so it has to use VIPER like callback structure instead of directly returning a value upon call.

Yet, every blog post, article and video that explains VIPER claims that it makes code testable for TDD.

Edit: There is a question unit testing void method which may seem to be the duplicate of this one, but my question is about the similar behaviour not how we test it, but how the architecture limits the approach (to my understanding atleast).

  • Are you basically asking how to test asynchronous interfaces? If so, that's not a trivial problem but one which is mostly solved. – Philip Kendall Apr 27 '18 at 13:46
  • How can VIPER be more testable if it increases methods' "side effects"? Every public method in viper's flow is returning void, how can a code be "more testable" using VIPER when it looks like its not? – Talha Apr 27 '18 at 13:48
  • 2
    @Talha When you return void and only talk to something you were told to talk to it is disingenuous to call doing that a "side effect". It's your one and only job. You're forgetting why real side effects are bad. – candied_orange Apr 27 '18 at 14:38
9

Oh it's possible. It just doesn't look like what you want it to look like.

What you're complaining about is the use of output ports1,2,3 to communicate results rather then returning results. Does this make testing more complicated? Yes. Then why do it? Because it gives you another layer of polymorphism.

When you return, you're returning to the caller. You have no choice. Nowhere else to go. That means the caller has to know how to deal with the result. If you have an output port you can send the result off to whatever knows how to listen to you. That is powerful.

Why is that powerful? Because you're always going forward. Always facing towards the abstraction. Using things the way they were meant to be used rather then sneaking up behind them. Abstractions work better when you're not hacking them.

To test this you have to know how design things that know how to listen to an output port. But you were going to do that anyway. So what's the problem?

The problem is so many people get caught up thinking structurally. "All I'm doing is testing that a method got called". No. You're testing that a message, that communicates a result, got sent. If, in this mini output port language, that looks like a method call, fine. "But that's an implementation detail!" No. That's part of the output port language. What anything does with that message is up to them. What gets done with it is the implementation detail.

"But it's such a pain to test!" Well yes it is. But you decided to use it so it's your own fault. "So I should never use it?" No, you should use it when it does something useful for you, when you understand it, and when you think it's worth the pain it causes.

  • Doesnt that makes it as testing in BDD environment? Criminals (bugs) of pure business logic can still slip through though, right? Or should I accept the fact that this architecture is rather inspiring BDD than Unit Tests (unit test in my opinion is testing business logics). – Talha Apr 27 '18 at 13:55
  • 3
    Interesting business logic needs the most testing. Boring structural code that makes no decisions needs the least. Which is why "test everything" strategies so often fail. The point of tests is to help me read code. To understand what it does. If you're not helping me do that knock it off, you're just adding noise. – candied_orange Apr 27 '18 at 14:00

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.