Testing listeners in Laravel 5.1 - unit-testing

Is there an standard way to unit test Listeners in Laravel 5.1 (not mocking the Event::fire()) or do you just instantiate it, call handle() with mocked params and make assertions, the oldschool way?
I read Events and Testing and it doesn't really says anything about unit testing listeners.

AFAIK it's totally up to you and your preferences. You could do either of the two approaches mentioned, but I actually don't test them at all. Instead I try to have only a very basic code in the Listener, and move all the logic into separate services. IMHO that makes code easier to understand and cleaner to unit test without mocking the hell out of it.

Related

Is it still unit testing, when I write a WebInterface?

I have a more general question:
Assuming I have a web application, for example using the Struts2 Framework.
Therefore it becomes quite complicated to write Unit tests for functions, as you have to mock every aspect of the Framework.
The Database+Connection, The Session, a LDAP-Connection or what ever else is needed, which I do not have written on my own
It would be much easier to write the unit Tests so, that they run in a WebInterface inside the Base-Application, as all these things then already would exist.
The question:
Would you guys still consider this as unit testing?
Some thoughts..
The question is very general. My suggestion is that you still want to write some sort of Unit Tests for number of reasons. Firstly you can run them as an automated test suite so if something breaks you know quickly. Secondly you get a better designed system - Your objects are loosely coupled. You get more confident on the code you write.
If you have a framework harder to test,
a. Try abstracting away some dependencies, so they code can be injected without interfering with real instances.
b. Use a testing framework that can break any tightly coupled harder dependencies.
Harder to provide a comprehensive answer, but this is the general direction, which I would suggest.
You should consider what you really want to test first. A framework, for its definition, will use the classes you provide to do some "magic". Do you want to test that has already been tested "magic" or the business core of the app you programmed?.
Also, something you should consider, is where to stop testing. You probably don't want to test the connection to the database (considering what you wrote) so just mock it.
Take in consideration that you will have to test just one functionality at the time, don't think of having, for example, the database connection and the ldap in the same test, it wouldn't be unit testing.
Take a look at this tutorial also :http://tutorials.jenkov.com/java-unit-testing/index.html

Is it wise to defer unit-testing until integration tests pass in scenarios where behavior of a 3rd-party API is largely unknown?

I don't mean defer all unit-testing until an integration test passes. The unit tests I'm referring to are those that verify that the SUT interacts with the 3rd-party mystery API correctly.
The rationale for deferring these unit tests is that they verify something that is unknown. If I don't know how the 3rd-party mystery API works, how can I even write a unit test to ensure that the SUT uses the 3rd-party API correctly? Only once some minimal integration tests pass do I actually know what behavior to verify.
Of course, all other unit tests should be written before the SUT is written in the usual way (red, green, refactor).
Under the assumption that it's an external api I'd argure that your tests probably wouldn't qualify as a unit test anyway. They'd be integration tests.
How about writing a mock to test your code as is and then writing proper integration tests when you can access the 3rd party api? Also, if you're unit testing third party stuff, then your build will fail as soon as those things are unavailable which might be a problem in the long run.
A few years later, I have done much more unit testing, and feel I understand this better. Unit tests are good at verifying that a piece of code is correct ASSUMING that you correctly understand how to use the API's that are faked (mocked / stubbed). But to fake out those API's correctly, you must first understand how they work. So after reading the documentation for those API's, you can check your understanding by doing a proof-of-concept--even if that means testing code manually after writing it--or by writing an integration test. Once you are semi-comfortable with your understanding of the thrid-party API, you can fake it in a unit test and follow TDD once again.
Wrappers for third-party API's are an excellent thing to write integration tests for, where you merely test your minimal wrapper without faking the third-party API to ensure you correctly understand it. Some of these tests might not really be tests, but demonstrations written like tests. They come in handy later, too, because you can review them if you forget how something works, help a coworker understand the API, and discover subtle breaking changes when you upgrade the API.
Today, I often write integration tests of wrappers, write demonstrations / examples of third-party API's exercising corner cases relevant to my situation, and even write production code and manually test it if I have to. I only have to when there is an ambiguity or unclarity in the API I'm using. Once I feel confident about how to use it, it's time for "normal" TDD.

Mock Objects vs Test Database

What's the advantage of using mock objects in comparison to a static test database that has known data and using transactions to make sure nothing changes when testing against the database.
You can do both. Use mock objects to test you BLL logic and then use a test database to test your DAL logic. That way if something breaks you can easily see where the problem lies by which test fails.
Firstly, using a mock will be much quicker than connecting to an external database. However the main reason is that mocks behave the same each time the test is run, which you can't guarentee with an external service like a database, which means unit tests don't fail randomly. You can also easily simulate any types of failure you want to handle with a mock object.
It's also a good idea to run integration tests against a real database however to test things like configuration and performance.
If you can ensure that the static test db doesn't change during testing then I think static test db is better than mock objects. But, then it depends on what you want to test and the complexity of the code being tested. I would go with mock objects as they are simpler to maintain compared with a db.
Imagine you're about to write a class which doesn't exist. Maybe it's a controller. It's not something which talks straight to the database.
You have a good idea of how it ought to behave, and you know what it should be responsible for, and what it should delegate to some other service (using Single Responsibility Principle). So you write interfaces to represent the roles of the helper classes it's going to use.
Then you write an example of how you might use your class that you're about to create. If you like, you can call the example a unit test. You mock out the interactions with the helper classes. When you run the example, it fails, because you haven't written the code yet. You can now write the code to make it pass, using the interfaces of the helper classes - which you also haven't written yet.
Then you do the same with the helper classes, mocking out their helpers.
Eventually you'll reach a class which talks to the database. Or maybe it talks to a web service. Or perhaps the data is static, or in memory. (It doesn't matter to the original class, because your class is decoupled from this).
At this point you'll want an example to describe the behaviour of this class, too, and if it's a database connector, you'll need a database for the example.
Writing code this way produces code that's easy to use and understand, with nothing extra that isn't needed by something further up the stack. This is usually more robust than code that's easier to write. That's why we sometimes use mocks - because writing tests first using mocks helps produce good, maintainable, decoupled design.
Usually you would use both of these approaches.
For unit tests you would use mocked objects. This way you can test your system in a much more fine-grained way, because you can mock every object - not only the ones that wrap the database connection. In general it is good practise to unit test every class in separation of all the dependencies. The benefits are - its is possible to test all the error handling on all levels and make sure you test all the code paths, when you get a test failure you can immediately find the cause, etc.
For integration and end-to-end tests you test big parts of the system or the whole thing. Then you would connect to the database (because this connection is part of the test). Obviously you have to ensure that the database is in a known state, etc., etc.
You will end up having much more unit tests than integration tests, so its actually quite important to make them very quick - yet another advantage of using mock objects.
The setup for testing with a db can be arduous. If you find yourself spending more time in setting up the db, just to test some functional aspect of your business logic, then you might want to use a mock/fake.

Deploying a big test disguised as a program

If someone has created a small diagnostic, internal web app that uses (unit) tests as its logic, is there ever a valid reason to do that? Keep in mind that Nunit has to be deployed as well where ever this website goes.
I'm of the view that programs should contain their own logic and possibly reusable parts (if available) but not wrap tests for their logic. Tests serve the purpose of validation for code logic. If you than say tests are going to be code logic, shouldn't you need to write tests to validate the tests? Why is that fundamentally wrong?
Hint: Because now you are stringing all of these tests together and interrelating them, which means they are no longer dependent(?).
Using a Unit test framework for something else than unit tests is usually not the most proper path. You don't have to write tests for your unit tests, since you write them first and see them fail. That's how you know they're working properly. I'm guessing testing code written within a unit test framework is nontrivial, and if I had a diagnostics app for a critical piece of software, I would really like to be certain it worked as it should.
Edit: It seems that you've already made up your mind but need support in expressing why the current strategy is less than ideal to, perhaps, other project members. If that's the case, I suggest you put your code where your mouth is, and throw together a small sample app designed differently. If utilizing a unit test framework in this specific case was a bad design decision, then that would make it clear as sunshine.
I'm pretty sure if you look at this question TDD Anti-patters catalogue, you will find that you are commiting sever anti-patterns.
Code is code. Just because it's labeled a test doesn't mean it's not also a useful application.
Suppose we need to write a lot of verifications of beahviour. Why is using test framework a bad idea? SHoudl we instead write a new framework with identical function and call it something different?
Take an external view. This applciation claims to do certain things. Does it do them correctly? reliably? Can it be maintained, enhanced? Understood?
If so, why do you care that it happens to use a test framework in its implementation. If its behaviour or structure are defective then we criticise.
One lovely thing about great technology is that it has unexpected applications.
The purpose of unit testing is to make sure your class works the way it should and according to the interface. So if you are using your unit tests for some testing app it seems like using assert in programm logic.
If you need some testing app - implement it and use WITH unit tests. It maybe to configure something or to get some user interaction.
One of the other reasons I see - unit test are written according to assumptions on how everything works. If your assumption is right tests should pass. When adding functionality unit tests let you feel confident that all assumptions are still there. So every test should be kept as simple as you can keep it. that`s why no need to test test code and no need to use testing code in any testing applications.

Using the main method of classes for debugging?

It is good practice to use the main method to test a java/.net class?
I've seen it reccommended in some text books, but to me it seems like using a unit testing framework would make more sense...
The main method gives you one point of entry to the class and you can test one aspect of the classes functionality. You could I guess test many but it doesn't seem to make sense as much as using Junit or Nunit.
One obvious advantage seems to be that you can whitebox test the class. That is, you can test the internals of it (private methods for example). You can't do that with unit-tests, nor would you wan't that, they are primarily there to test the interface and the behavior from the users perspective.
I think it could be useful to develop integration tests that are invoked from a main method -- like a test runner -- that tests suites of integration tests. I wouldn't do unit testing this way as unit testing frameworks provide a much better mechanism to do this.
[EDIT] To clarify, I'm not suggesting that each class have static main method to be used for integration tests, but rather that you could write an integration test program with a static main method that would run your suite of integration tests.
The main method can be useful for certain situations, but using a debugger and then writing a unit test (to provide some insurance against regressions) is a more robust solution.
In Java it's accepted to have multiple main methods and use them for testing however .NET doesn't allow this, if you have two mains in the same program you will get compiler error CS0017, and tells you to Compile with /main to specify the type that contains the entry point.
I've got to say the Java way makes more sense to me.