hemerajs / hemera

🔬 Writing reliable & fault-tolerant microservices in Node.js https://hemerajs.github.io/hemera/
MIT License
806 stars 70 forks source link

Proper way to test services #53

Closed pocesar closed 7 years ago

pocesar commented 7 years ago

I'm missing the proper way to test the services (the aither repo doesn't have any besides the load test), and couldn't find a definitive answer. In express, I used superagent, which made the REST testing somewhat easy, and doesn't need to listen on a port

StarpTech commented 7 years ago

Hi @pocesar we use NATS as transport layer so we cant emulate it for tests but you can look in the test directory there you can find a very simple way to testing your services. There is a package called hemera-testsuite with that you can start and stop the server. Thanks.

StarpTech commented 7 years ago

@prcesar it's the same scenario as with a http api. You should do unit tests to test your business code. You should do integration tests to test your stack. How to do integration tests you can see in the tests directory or in the documentation. Unit tests are independent from the used framework. If you have services which calls other services you have to mock that interface in your unit tests. I hope it is clear otherwise refine your question. Thanks!

StarpTech commented 7 years ago

If you have any ideas to create test utilities do not hesitate to make an approach. Please reopen when needed.

acehko commented 7 years ago

Hi @StarpTech Since hemera is used only with NATS, and is not transport independent, why not make the nats package a dependency of nats-hemera? Or make it optional. That way it would be a lot easier to test without the need to run nats. Then we could use something like hemera.start() to connect to nats.

pocesar commented 7 years ago

@StarpTech yes, it makes sense to test only the methods, like Seneca does

it wasn't obvious because the given examples use closures and doesn't separate each add from the implementation

StarpTech commented 7 years ago

@acehko it was a design decision that hemera isn't transport independent Overview. I won't emulate the NATS messaging logic. NATS function as router, transport layer. You don't have to start NATS if you write your code with testing in mind. Start with testing your business logic instead to cover it with an integration test.

acehko commented 7 years ago

@StarpTech I understand. But since hemera depends on nats, why is nats not a dependecy of hemera? Right now we need to pass a nats objec to hemera. For that reason we always need to use hemera-testsuite for unit testing.

What would be nice is to create a new hemera instance without connecting to nats. That way we could unit test without extra dependencies, and only connect to nats when we run the service in production. Something like this:

const heemra = new Hemera();
// Connect only in production
hemera.connect(natsURL);
StarpTech commented 7 years ago

nats-hemera means that hemera is tool for nats. Hemera should be small as possible and I seperate the hemera abstraction from the transport. You can also plug your own NATS Server when it match with the interface. I think you misunderstood it. Unit test aren't integration tests. You dont need NATS to do it.

Since we rely on NATS you have to start NATS to simulate a real scenario. For unit testing you can simple test your library.

A unit test is a test written by the programmer to verify that a relatively small piece of code is doing what it is intended to do.

An integration test is done to demonstrate that different pieces of the system work together. Integration tests cover whole applications, and they require much more effort to put together. They usually require resources like database instances and hardware to be allocated for them.

Reference: http://stackoverflow.com/questions/5357601/whats-the-difference-between-unit-tests-and-integration-tests

acehko commented 7 years ago

@StarpTech What you are saying makes sense. I was viewing hemera to be more like seneca than it actually is. As for testing, what I meant was that I want to test methods that were registered with .add without the need to run a nats server. I was wrong to call it unit testing.

StarpTech commented 7 years ago

@acehko great. btw you also has access to your server method without to start NATS.

const payload = hemera.router.lookup({ topic: 'math', cmd: 'add' }) //get by pattern
//call add method manually
const request = { a: 1, b: 2 }
payload.action(request, function(err,result) {
//result = 3
//be aware this function has no scope
})

But there is no way to just initialize node-nats without starting it. But I think it is easy to mock because you dont need NATS for unit testing.

class NatsMock extends EventEmitter {}
const hemera = new Hemera(new NatsMock)
const payload = hemera.router.lookup({ topic: 'math', cmd: 'add' }) //get by pattern
//call add method manually
const request = { a: 1, b: 2 }
payload.action(request, function(err,result) {
//result = 3
//be aware this function has no scope
})
StarpTech commented 7 years ago

@acehko https://github.com/hemerajs/hemera/blob/master/examples/unittest.js

StarpTech commented 7 years ago

@acehko @pocesar see the example we provide a small but neat feature to stub the act and add interfaces without to start NATS. https://github.com/hemerajs/hemera/blob/master/examples/unittest.js