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

Enhance Mocking: Allow it to work without direct access to Serialport instance #1452

Open
Apollon77 opened this issue Jan 25, 2018 · 17 comments
Labels
feature-request Feature or Enhancement
Milestone

Comments

@Apollon77
Copy link

Apollon77 commented Jan 25, 2018

  • SerialPort Version: 6.0.4
  • NodeJS Version: 6/8
  • Operating System and Hardware Platform: not relevant

I tried to add testing for a library that uses Serialport "inside". (https://github.com/hobbyquaker/cul). So I tried out the mocking possibilties and in general they are great, BUT in order to emit data or get the lastWrite I need access to the instance of Serialport used "inside" the library because i need to call e.g. serialportinstance.binding.lastWrite
The library itself normally do not expose the used instance to the outside world and because of struct mode and such I also can not simply access it from the outside.
So for now I ended up in adding a "getSerialport()" method to the library to return the instance ... but to have this only to allow testing feels weired :-(

Would it be possible to enhance the Mock class in a way that I can access the "connected serialport instance for a defined port" using astatic method? Something like

MockBinding.getConnectedInstance('WHATEVER_PORT_NAME');

or maybe already

MockBinding.getMockBindingForCinnectedInstance('WHATEVER_PORT_NAME');

to get directly the "serialportinstance.binding" instance to then use the methods on that in my "Outside tests".

That would really help, because so you can design the libraries without testing "backdoors" ...

Ingo

@reconbot
Copy link
Member

🤔 I approve of this idea. We can do half of this by exposing this object on the mock binding object. And then you have all the currently existing bindings. I have to think about a nice way to break encapsulation to get the port.

@Apollon77
Copy link
Author

My idea was to store the reference to the instance on "open" also in the ports object with the opened port (because only one open is allowed at all). But no idea how ;-))

@Apollon77
Copy link
Author

BTW: An alternative would be some kind og "passing through binding" where the created "virtual" portname can be opened twice and the instances are cross-bound testserial.write -> realserial.read and other way ... so kind of a "real" software virtual serialport. This would work too maybe (but I have no idea how)

@reconbot
Copy link
Member

reconbot commented Jan 25, 2018 via email

@Apollon77
Copy link
Author

But "echo" in this case means that anything that tís written by the real Serialport instance is echoed back to her ... this is not what I meaned.
Ma Idea was the possibility to define a "Virtual portname" and then being able to open it "from two sides". One side is the real logic/stuff you want to test and the other side simulates the "device" you communicate with. So anything that is written by the real logic comes as "on('data')" (comparabel to the "lastWrite in the Mock) in the second instance ... but the initial idea above works too

@reconbot
Copy link
Member

reconbot commented Feb 5, 2018

Oh you mean have another port that is the "other side" of the test one. 🤔

@Apollon77
Copy link
Author

Correct, both ways would work. Such a "virtual port" you can setup e.g. using socat ... but this is "high" effort for everyday testing :-)

@reconbot reconbot added the feature-request Feature or Enhancement label Feb 5, 2018
@siburny
Copy link

siburny commented Jun 23, 2018

https://github.com/reyiyo/virtual-serialport solves this problem by adding 'dataToDevice' event. Anytime something is written to the fake serial port it emits this event and allows you send data back based on your logic (which basically simulates a device). Unfortunately binding doesn't emit any events, so it's not easy to add it.

How I solved this is: I override write function of the instance of the SerialPort where I catch what's being written to the port, and queue particular responses.

@Apollon77
Copy link
Author

virtual-serialport only helps partially. I use it in several of my projects for testing by using "mockrequire" to completely moch serialport away and replace at test runtime with virtual-serialport.

But virtual-serialport is not updated to be compatible with all the serislport 6.x changes ... and so I tried the mock possibilities of serialport itself

@siburny
Copy link

siburny commented Jun 23, 2018

Yes, sadly, it's not updated yet. That's why I switched to node-serialport@6 and added write function overload.

@reconbot reconbot added this to the Next milestone Sep 15, 2018
@branylagaffe
Copy link

As the docs, the MockBinding class, and the virtual-serialport packages haven't been updated that much lately. Could it be possible to consider making an up-to-date interface dedicated to testing.

@reconbot
Copy link
Member

reconbot commented May 2, 2019

We do have mock bindings and it is up to date. However, we don't have the advanced features proposed in this issue. What are you asking?

@branylagaffe
Copy link

branylagaffe commented May 3, 2019

Imo the examples in the package could be showed in the website docs

About the testing features, I'was thinking about an interface made of helper functions, that could, by example, use the bindings to generate random dummy data. I don't know if it's relevant to this package ?

@reconbot
Copy link
Member

reconbot commented May 5, 2019

That's relevant to the mock package. Happy to take any prs about usage as you figure it out.

@jmbldwn
Copy link

jmbldwn commented Nov 8, 2021

I think what would help is if the mock binding could be a more complete emulation of the hardware, so I could write a piece of code that emulates the device I'm connecting to and plug it in.

To that end, an emulated device needs to get notified when a SerialPort client opens a mock port, receive data sent to it, and send data back (not echo-ing) at a minimum. Maybe MockBinding.createPort() could return an event emitter to attach open and data events?

@alexose
Copy link

alexose commented Apr 4, 2022

@jmbldwn Well said. Thank you for articulating the problem.

To add another data point: This is how I expected MockBinding would behave. It took me quite a while to realize that MockBinding was actually for mocking a port, and not mocking a device.

I guess it's reasonable from the perspective of the node-serialport devs, since the library is concerned with serial ports. But for the rest of us who are using it to transfer data to and from physical devices, it would be super useful to have a way to test that.

@Lucas-C
Copy link

Lucas-C commented Nov 17, 2022

I submitted a PR that provides MockBinding.getOpenMockPort(): serialport/binding-mock#20

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Feature or Enhancement
Development

No branches or pull requests

7 participants