c# - Asynchronous TDD - Test Class blocks -
how create unit test test class sits in loop?
here's scenario.
i have class injected reference serial port.
the class has method called send(string data);
this public method invokes aysnchronous private method actual work.
the class under test (cut) should following when method called.
1) split string chars.
2) send char
3) wait char echoed
4) send next char (repeat until chars sent)
so after sending first char cut sit in loop waiting echo until receives 1 or times out.
the problem have once cut has entered loop block test class until times out.
since need test class send echo cut im stuck.
to test i've created mock serial port , im using nunit.
the test below. idea after sending test string wait cut respond. each time cut writes char serial port wait cancelled , write echo serial port , cut responds sending next char.
[test] public void test() { _serialport.datasentevent += new eventhandler(_serialport_datasentevent); _completedsync = new manualresetevent(false); _wrapperport.send("test"); _completedsync.waitone(1000); // wait first char assert.areequal("t", _serialport.bufferout); //first char sent _serialport.bufferin = "t"; //write echo _completedsync.waitone(1000); //wait second char assert.areequal("e", _serialport.bufferout); //second char sent //...etc } void _serialport_datasentevent(object sender, eventargs e) { _completedsync.set(); }
but happens cut blocks send("test") called , control returns test class once cut has timed out waiting echo.
since send method being completed on thread why blocking test class?
i think mix implementation details test.
you have specified serial port protocol precisely, define interface describes protocol:
public interface iserialport { event eventhandler echo; void send(char c); }
this interface forces me send 1 character @ time. serial port wrapper work correctly when consumes interface correctly. this approach requires additional wrapper class real serial port. class needs handle async operations in order implement interface properly.
with testserialport
, can write test follows:
[testmethod] public void send_data_as_chars_to_serial_port() { const string data = "test"; var serialport = new testserialport(); var wrapperport = new wrapperport(serialport); wrapperport.send(data); assert.areequal(data, serialport.buffer); assert.areequal(data.length, serialport.sendcount); }
the testserialport
implements interface, simulates real serial port behavior, , exposes data test can assert:
public class testserialport : iserialport { public string buffer; public int sendcount; public void send(char c) { sendcount++; buffer += c; echo.invoke(this, eventargs.empty); } public event eventhandler echo; }
one possible implementation satisfies above test:
public class wrapperport { private readonly iserialport serialport; private queue<char> buffer; private char current; public wrapperport(iserialport serialport) { this.serialport = serialport; serialport.echo += onecho; } public void send(string data) { buffer = new queue<char>(data); sendnextcharacter(); } private void onecho(object sender, eventargs e) { sendnextcharacter(); } private void sendnextcharacter() { if (buffer.any() == false) return; current = buffer.dequeue(); serialport.send(current); } }
Comments
Post a Comment