Fredrick
Fredrick

Reputation: 1310

How do I unit test a root ViewModel with multiple layers of children?

I am having difficulty writing tests for a particular ViewModel which ties together several other ViewModels and their children. It's the most complex ViewModel in my application.

My ViewModel's structure mirrors the view's structure. It is injected with its children and its children are injected with their children.

It is very laborious to mock.

It is time consuming to mock due to the chain of dependencies. For example, say I have the structure MainViewModel.SubViewModel1.SubViewModel2 than I end up having to mock multiple layers because an action in MainViewModel may result in SubViewModel1 needing to check the visibility of SubViewModel2.

Is this the result of poor design?
Am I unit testing incorrectly?
Are there AutoMockers that will recursively mock my injected parameters?

Upvotes: 3

Views: 376

Answers (2)

Sunny Milenov
Sunny Milenov

Reputation: 22320

The answer to your Q2 "Am I unit testing incorrectly" is "probably". Unit testing is about testing units in isolation. But some times its hard to do. You have few options:

Make SubViewModel1 to have a property which exposes the visibility of SubViewModel2, that way, when testing MainViewModel, you will mock/stub only SubViewModel1. And of course you will have a test if that property actually works :)

Now, the above is from "puristic" point of view. Sometimes, even if its the right thing to do from OO design point of view, it's not practical to do so.

So, you can try AutoFixture as an auto-mocking container, and it will prepare nested mocks.

Again, review your design, usually if you find out that something is hard to test, probably it's not well constructed, and does too much.

Upvotes: 2

Viv
Viv

Reputation: 17398

Well it's very easy to say it's bad design and it can tend to be so as well.

However there are cases that might require this. If your sure your in one of them cases then you got to live with it. If it's your most complicated VM then it's just logical that testing it will be your most complicated tests.

  • For functional tests, since actions in that will affect properties in other grand-children VM's(as per your dependencies), your tests if valid should be testing for all of that which means you can't and shouldn't really be mocking them as if you do so, your not really testing that VM properly.
  • Now for unit tests, your only concerned with this VM and thus your mocks should be only for the direct children dependencies. Even if logic requires the grand-children you can just make the mock layer VM simulate it and return results accordingly. So at-most you only have your Testing VM with one layer of children in 99% cases(exclusions always apply in these things)

Finally I hope you do have some interface structure among your VM's to help you mock VM's accordingly. This will help you in such cases as if your using an IoC container you can in your tests just inject the Mock VM instead of the live one. This can either be an interface on the VM itself or quite a lot of people do prefer to extract these behaviors out into a service.

Upvotes: 2

Related Questions