-
Notifications
You must be signed in to change notification settings - Fork 841
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unit Test examples for testing the interactors in Mosby MVI #272
Comments
Hey here, what exactly do you want to test? We had a discussion lately (see #168) where I have explained why I think integration testing makes more sense especially with MVI. You may find this approach on testing interesting too. Would like to hear your feedback. |
Hi again, Yes, interactors (business logic) only. Don't want to test anything related to Mosby. It seems like #168 doesn't have anything related to testing? Maybe a typo? Regards |
Hi, This took some time 😄 TL; DR I want to test my "business logic" and don't want my tests coupled with the delivery mechanism. I don't want my tests to know anything about the existence of Presenters. The long version: Read the discussion at #268 and your posts about MVI (about 2-3 times). Also, watched Uncle Bob's Clean Coders videos on TDD and Clean Architecture lectures. I want my tests to be:
I believe that the argument should be "Why skip the Interactor and test the Presenter?". Since the latter will require (much) more work to test properly. For the sake of argument, let's review why Interactor testing is a must (In my opinion, of course):
assertEquals(expectedViewState, viewState) That is, of course, because MVI just is a presentation pattern. It shouldn't dictate how we architecture or test our app. With all that being said, I don't believe that Mosby does anything wrong. Just saying that good samples should include proper testing of Interactors. Feel free to ask, if any questions arise! 🙂 |
Thanks for taking the time to write down your feedback. Regarding your original question: @Test void interactorIsReturningFoo(){
Observable<Foo> observale = interactor.doSomething();
Foo foo = observable.blockingFirst();
assertEquals(expectedFoo, foo);
} and so on ... But I don't understand how this is related to MVI or Mosby?
This is not a Presenter Test, this is a Integration test as it tests all layers down from Presenter inclusive Business Logic state reducer etc. Perhaps we have a different understanding / definition of what a presenter test is. The only "Test Double" in this test is the View Layer, but this could easily be run on a real android view too.
I see your point, but I have a different opinion about that which I think comes from the fact that you are advocating for writing unit tests on business logic / Interactors whereas I recommend to write more integration tests instead of unit tests. So the question is: where does a integration test begins? If you have two parts in your business logic an put them together and test them together then it is already an integration test. From my point of view integration tests should cover as much as possible, ideally from (android) View layer to the deepest part of your business logic and all the way back. Unfortunately, real android view tests (instrumentation tests) are slow, hence often we mock the View layer. Nevertheless, I recommend to write integration tests with android View layer running on a real android device. Hence, in most cases I would draw the boundary of my MVI based app (Black vertical line in the diagram) between view (interface) and presenter unless Presenter is really android specific which I only rarely can remember that this was the case in one of my apps. Either android specific components were in the view layer or the very end of the business logic like a sqlite database. Both implementation details should be hidden behind a Interface (boundary).
That is the big advantage of integration testing. You see your whole app as a single big black box. The View Interface defines the boundary and usually that is all you need to know. Think of it in a mathematical way. If you have a mathematic function definition like this:
then the only thing you need to know to test this function is the public api this function offers: inputs x, y and the return value. But you don't care about the implementation detail (x+y). If you apply that idea on a app:
So if
i don't understand the question but if your question is if I take my app and replace the android View with a website or whatever else then your website obviously have to implement the View Interface and that's it. No need to change other internals (implementation details) within the Boundary (Black vertical line in the diagram) .
Again, we might have a different definition of what a presenter test is. I, personally, prefer integration test over unit tests. If you write unit tests for Interactor, State Reducer and Presenter in isolation, you can never be sure that they integrate and work together as expected. this is a nice illustration of the issue with unit tests: https://twitter.com/ThePracticalDev/status/845638950517706752 So you may need some kind of integration test for those components anyway. But then, what is the point of writing integration and unit tests? You gain nothing if you test things twice.���
It sounds rough, but yes you should, otherwise it is not an integration test since this one Use Case is interacting with other parts too, right (otherwise it is exactly the same presenter as an already existing one which is senseless)? Also this ensures that if you refactor that use case, you are sure that it works for all presenters / screens that use this use case, which is not 100% guaranteed if you just write a single unit test for the use case.
There is exactly one "Test Double" for the View layer. Everything else are the real app components so the promise:
still holds (if you write integration tests / black box tests aiming to cover all components) because it is exactly like:
|
Thanks for taking the time. This is a real treat 👍
As I stated previously
Yes, it is not related to Mosby. I am perfectly fine with not addressing this issue here.
I completely agree. It is an integration test. Integration tests have a (very large) place in developing "proper" apps and should cover all the things you've mentioned. MVI is awesome beyond a reasonable doubt, I completely agree here.
Yes, that is correct. I am talking about going to Web (for example) from Android. Let's have another look at the diagram: The presenter is outside the black vertical line. That makes sense because the presenter prepares ViewModels that are specific for the view. Take for example an Android app that displays a Todo list. Each Todo ViewModel is composed of {name, dueDate, isCompleted} and all is great. Now, you want to present that list via a Web page. Due to the large screens that Web apps are displayed on, we (the designer) decides to display the duration of a task. A GUI is added for editing it, as well. So, we need new ViewModel and Presenter to handle all that. Again, Integration Tests are needed to ensure that everything is glued together correctly. What I meant by that:
is the fact that we have to use "Test Double" for every one of our tests. Test doubles make testing a bit harder to write and read compared to testing return values of methods. I would prefer to write simpler tests whenever I can, I tend not to skip writing them when that is the case 😄 Personally, the promised simplicity, explicit state presentation and immutability by MVI are there only if my tests are simple to write & read too. Again, thank you for your time! |
Hi,
Not 100% sure if this should be here or on SO, but it looks like a "feature request" so...
Reading the series of blog posts (starting here: http://hannesdorfmann.com/android/mosby3-mvi-1) I stumbled upon the following lines:
From what I've implemented so far, all of this seems to have a lot of merit. I use mosby (mvi) + mosby-conductor (mvi) + conductor and couldn't be happier. I write Interactors or UseCases (or whatever they should be called) using RxJava and want to unit test them. After all, the real logic of the app is there and I want to test it without much of a hassle.
I would imagine unit testing an Interactor should look something like this:
I would imagine this should work whether or not State Reducer is used. I believe I checked every relevant sample but couldn't find one that delivers.
Can we see some kind of an example related to all that? And, please, no presenter testing code. Of course, all of this might not be relevant to mosby at all. Still, this might be helpful for the community.
Thanks for the great library!
The text was updated successfully, but these errors were encountered: