Skip to content
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

How do I unit test a class using TaskService #602

Open
dahall opened this issue Apr 14, 2018 · 9 comments
Open

How do I unit test a class using TaskService #602

dahall opened this issue Apr 14, 2018 · 9 comments

Comments

@dahall
Copy link
Owner

dahall commented Apr 14, 2018

Is there anyway to unit test and mock core classes in this framework without using Moles like framework? Wondering if developers has any plans to introduce Interfaces for TaskService, TaskFolder, Tasks and other core classes in this library.

Originally posted: 2015-01-30T08:56:49

@dahall
Copy link
Owner Author

dahall commented Apr 14, 2018

As the developer, I do not have any plans to introduce a set of unit tests for this project. If you do, please contact me and I will add them.

Originally posted: 2015-01-31T21:41:28

@dahall dahall closed this as completed Apr 14, 2018
@bouchraRekhadda
Copy link

Hello @dahall, we started using your library in order to create an launch scheduled tasks in remotes machines and it works perfectly. The class using TaskService to register the task is unfortunately not tested yet!
Are you willing to use interfaces for TaskService & Task in particular ? if yes when will it be available (to avoid wrapping all (used) the library classes in custom interfaces)?

@dahall
Copy link
Owner Author

dahall commented Nov 28, 2018

I do not understand your request. Please rephrase or elaborate.

@bouchraRekhadda
Copy link

My basic question is, how can i mock in unit tests your library classes: in particular TaskService & Task ?

@dahall
Copy link
Owner Author

dahall commented Nov 28, 2018

I've never done 'mock' unit testing before, so I'm not sure what it requires. I'm happy to review and accept a push request if you'd like to do whatever work is needed.

@dahall dahall reopened this Nov 28, 2018
@dahall dahall self-assigned this Nov 28, 2018
@bouchraRekhadda
Copy link

I will give it a try. But basically the idea is to enforce dependency injection an using Interfaces to expose services, this way the unit tests will be much easier. If we had something like:
class TaskService: ITaskService
With ITaskService exposing all the current public TaskService class methods/properties, it would allow us to mock the class behavior

@dahall
Copy link
Owner Author

dahall commented Dec 5, 2018

Can I assume the interfaces need to be public? I remembered some similar work I'd started a couple of years ago for a different purpose. Would the attached file be what you're after (assuming all real classes were augmented to derive from these interfaces)?
Models.pdf

@bouchraRekhadda
Copy link

Hello @dahall sorry for the delay. Yes the interfaces should be public in order to be use by Mock. The interfaces described in the document are what is needed but they are internal.
For a matter of deadline i couldn't work on the pull request, i have managed to use wrappers around some of the library classes and i was able to unit test my code.

@fyndor
Copy link

fyndor commented Jan 23, 2019

That is what I ended up doing as well. I wrote wrappers around all the classes I needed from this library. I then created my own interface that these wrappers implement that represents the public functions of the wrapper. My business logic and tests use this interface. For the tests I use a mocking framework to create a mock version of the interface which is used in the test to prove things like did my code create a scheduled task when it was expected to etc. For the actual program, the classes that need this library have my interface as one of the constructor arguments and I use a dependency injection framework to instantiate these classes so for classes that need these interfaces it injects an instance of my wrapper.

This is actually the same pattern I use for things like the System.IO.File. In a unit test you don't want to have anything really create a file etc just like you don't want to really create a scheduled task in test. The File class doesn't provide an interface (it can't, its static), so I write my own IFile interface that describes the methods I want to use off of the File class and then I write a wrapper that implements this interface and for each method all it is really doing is calling the actual method on the real File class.

If library developers always provided interfaces for all their public classes which described the public properties and methods, that would make testing much easier. In most cases that would mean I don't have to spend time writing my own interface and wrapper class for each of your classes I want to use. I am talking about "business" classes and not model classes that are comprised of a set of properties with safe types on them (int, string, etc). The one caveat is that if you have model class and one of it's properties stores an instance of one of your business classes, instead of storing an instance of that class it should store an instance of that classes interface instead. That way if that model is somehow involved in one of my tests then I can just assign a mock instance for that property. You could provide interfaces for all your public business classes, but if they have functions that take a model class as an input or return it as an output and if it has a property that is a business class then I end up having to write a wrapper for the model, which means I then can't even use your business class interfaces and I end up having to write my own anyway. All it takes one concrete business class in any of your interfaces or your models and then I have to write my own wrappers anyway.

Granted library authors don't have to always do that for everything. But if they understand what unit tests want then they can know which classes we need them to write interfaces for. Any class that can read or modify the state of the computer or any other system outside that computer then the class needs an interface. So if it does something with files, registry, network, etc then it needs to be an interface. I might be missing something, but that is basically it. The one exception I can think of is if you have a class that doesn't meet that criteria, but it does something computationally expensive (bunch of slow running math etc), then an interface would be nice there too. We want our tests to be fast. In our tests we are not testing your class itself but rather did our code send the correct values to your class's methods and did we take the results from your methods and do the right things with them. If your class doesn't touch the outside world and it's operations are fast then I will probably just your real classes in my tests if it saves me time.

Repository owner deleted a comment from dickxuwen Nov 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants